diff -Nru kodi-20.1+git20230312.0705-289ec664e3/addons/skin.estuary/xml/Custom_1109_TopBarOverlay.xml kodi-20.2+git20230630.0528-5f418d0b13/addons/skin.estuary/xml/Custom_1109_TopBarOverlay.xml --- kodi-20.1+git20230312.0705-289ec664e3/addons/skin.estuary/xml/Custom_1109_TopBarOverlay.xml 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/addons/skin.estuary/xml/Custom_1109_TopBarOverlay.xml 2013-05-12 08:41:54.000000000 +0000 @@ -1,6 +1,6 @@ - Skin.TimerStart(1110_topbaroverlay) + Skin.TimerStart(1109_topbaroverlay) Window.IsActive(fullscreenvideo) | Window.IsActive(visualisation) Window.IsActive(seekbar) | Window.IsActive(pvrosdchannels) | Window.IsActive(pvrchannelguide) DepthOSD @@ -10,7 +10,7 @@ ![Player.ShowInfo | Window.IsActive(fullscreeninfo) | Player.ShowTime | Window.IsActive(videoosd) | Window.IsActive(musicosd) | Window.IsActive(playerprocessinfo) | Window.IsActive(pvrosdchannels) | Window.IsActive(pvrchannelguide)] + [!String.IsEmpty(Player.SeekNumeric) | Player.Seeking | Player.HasPerformedSeek(3) | Player.Forwarding | Player.Rewinding | Player.Paused] | !String.IsEmpty(PVR.ChannelNumberInput) VisibleChange - Conditional + Conditional 0 0 diff -Nru kodi-20.1+git20230312.0705-289ec664e3/addons/skin.estuary/xml/MusicVisualisation.xml kodi-20.2+git20230630.0528-5f418d0b13/addons/skin.estuary/xml/MusicVisualisation.xml --- kodi-20.1+git20230312.0705-289ec664e3/addons/skin.estuary/xml/MusicVisualisation.xml 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/addons/skin.estuary/xml/MusicVisualisation.xml 2013-05-12 08:41:54.000000000 +0000 @@ -95,7 +95,7 @@ 20 100 - 40 + 35 font37 black @@ -105,7 +105,7 @@ auto - 40 + 35 font37 black diff -Nru kodi-20.1+git20230312.0705-289ec664e3/addons/skin.estuary/xml/Timers.xml kodi-20.2+git20230630.0528-5f418d0b13/addons/skin.estuary/xml/Timers.xml --- kodi-20.1+git20230312.0705-289ec664e3/addons/skin.estuary/xml/Timers.xml 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/addons/skin.estuary/xml/Timers.xml 2013-05-12 08:41:54.000000000 +0000 @@ -9,8 +9,10 @@ Dialog.Close(videoosd) - 1110_topbaroverlay + 1109_topbaroverlay A timer that is activated when the topbaroverlay is loaded and stops automatically after 5 seconds (or playback is resumed) - !Player.Paused | Integer.IsGreaterOrEqual(Skin.TimerElapsedSecs(1110_topbaroverlay),5) + Window.IsActive(1109) + [Player.Seeking | Player.Forwarding | Player.Rewinding | Player.HasPerformedSeek(1)] + Player.Seeking | Player.Forwarding | Player.Rewinding | Player.HasPerformedSeek(1) + Integer.IsGreaterOrEqual(Skin.TimerElapsedSecs(1109_topbaroverlay),5) | Player.Playing diff -Nru kodi-20.1+git20230312.0705-289ec664e3/BUILDDATE kodi-20.2+git20230630.0528-5f418d0b13/BUILDDATE --- kodi-20.1+git20230312.0705-289ec664e3/BUILDDATE 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/BUILDDATE 2013-05-12 08:41:54.000000000 +0000 @@ -1 +1 @@ -20230312 +20230630 diff -Nru kodi-20.1+git20230312.0705-289ec664e3/cmake/modules/buildtools/FindFlatC.cmake kodi-20.2+git20230630.0528-5f418d0b13/cmake/modules/buildtools/FindFlatC.cmake --- kodi-20.1+git20230312.0705-289ec664e3/cmake/modules/buildtools/FindFlatC.cmake 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/cmake/modules/buildtools/FindFlatC.cmake 2013-05-12 08:41:54.000000000 +0000 @@ -25,14 +25,15 @@ OUTPUT_STRIP_TRAILING_WHITESPACE) string(REGEX MATCH "[^\n]* version [^\n]*" FLATBUFFERS_FLATC_VERSION "${FLATBUFFERS_FLATC_VERSION}") string(REGEX REPLACE ".* version (.*)" "\\1" FLATBUFFERS_FLATC_VERSION "${FLATBUFFERS_FLATC_VERSION}") + endif() - else() + set(MODULE_LC flatbuffers) + # Duplicate URL may exist from FindFlatbuffers.cmake + # unset otherwise it thinks we are providing a local file location and incorrect concatenation happens + unset(FLATBUFFERS_URL) + SETUP_BUILD_VARS() - set(MODULE_LC flatbuffers) - # Duplicate URL may exist from FindFlatbuffers.cmake - # unset otherwise it thinks we are providing a local file location and incorrect concatenation happens - unset(FLATBUFFERS_URL) - SETUP_BUILD_VARS() + if(NOT FLATBUFFERS_FLATC_EXECUTABLE OR (ENABLE_INTERNAL_FLATBUFFERS AND NOT "${FLATBUFFERS_FLATC_VERSION}" VERSION_EQUAL "${FLATBUFFERS_VER}")) # Override build type detection and always build as release set(FLATBUFFERS_BUILD_TYPE Release) diff -Nru kodi-20.1+git20230312.0705-289ec664e3/cmake/modules/FindCrossGUID.cmake kodi-20.2+git20230630.0528-5f418d0b13/cmake/modules/FindCrossGUID.cmake --- kodi-20.1+git20230312.0705-289ec664e3/cmake/modules/FindCrossGUID.cmake 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/cmake/modules/FindCrossGUID.cmake 2013-05-12 08:41:54.000000000 +0000 @@ -29,7 +29,8 @@ endif() set(patches "${CMAKE_SOURCE_DIR}/tools/depends/target/crossguid/001-fix-unused-function.patch" - "${CMAKE_SOURCE_DIR}/tools/depends/target/crossguid/002-disable-Wall-error.patch") + "${CMAKE_SOURCE_DIR}/tools/depends/target/crossguid/002-disable-Wall-error.patch" + "${CMAKE_SOURCE_DIR}/tools/depends/target/crossguid/003-add-cstdint-include.patch") generate_patchcommand("${patches}") diff -Nru kodi-20.1+git20230312.0705-289ec664e3/cmake/modules/FindGLX.cmake kodi-20.2+git20230630.0528-5f418d0b13/cmake/modules/FindGLX.cmake --- kodi-20.1+git20230312.0705-289ec664e3/cmake/modules/FindGLX.cmake 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/cmake/modules/FindGLX.cmake 2013-05-12 08:41:54.000000000 +0000 @@ -20,7 +20,7 @@ find_path(GLX_INCLUDE_DIR NAMES GL/glx.h PATHS ${PC_GLX_INCLUDEDIR}) -find_library(GLX_LIBRARY NAMES GLX +find_library(GLX_LIBRARY NAMES GL PATHS ${PC_GLX_LIBDIR}) include(FindPackageHandleStandardArgs) diff -Nru kodi-20.1+git20230312.0705-289ec664e3/debian/changelog kodi-20.2+git20230630.0528-5f418d0b13/debian/changelog --- kodi-20.1+git20230312.0705-289ec664e3/debian/changelog 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/debian/changelog 2013-05-12 08:41:54.000000000 +0000 @@ -1,4 +1,4 @@ -kodi (6:20.1+git20230312.0705-289ec664e3-0~jammy) jammy; urgency=medium +kodi (6:20.2+git20230630.0528-5f418d0b13-0~jammy) jammy; urgency=medium [ kodi ] * autogenerated dummy changelog Binary files /tmp/tmp0494x1gt/MJX0YBSrAp/kodi-20.1+git20230312.0705-289ec664e3/media/splash.jpg and /tmp/tmp0494x1gt/sM8lXWDhZ_/kodi-20.2+git20230630.0528-5f418d0b13/media/splash.jpg differ diff -Nru kodi-20.1+git20230312.0705-289ec664e3/system/settings/settings.xml kodi-20.2+git20230630.0528-5f418d0b13/system/settings/settings.xml --- kodi-20.1+git20230312.0705-289ec664e3/system/settings/settings.xml 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/system/settings/settings.xml 2013-05-12 08:41:54.000000000 +0000 @@ -2580,7 +2580,7 @@ 1 false - + -1 diff -Nru kodi-20.1+git20230312.0705-289ec664e3/tools/android/packaging/xbmc/src/channels/util/TvUtil.java.in kodi-20.2+git20230630.0528-5f418d0b13/tools/android/packaging/xbmc/src/channels/util/TvUtil.java.in --- kodi-20.1+git20230312.0705-289ec664e3/tools/android/packaging/xbmc/src/channels/util/TvUtil.java.in 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/tools/android/packaging/xbmc/src/channels/util/TvUtil.java.in 2013-05-12 08:41:54.000000000 +0000 @@ -209,7 +209,12 @@ builder.setMinimumLatency(10000); Log.d(TAG, "Scheduled channel creation."); - scheduler.schedule(builder.build()); + + try { + scheduler.schedule(builder.build()); + } catch (IllegalStateException e) { + Log.w(TAG, "TvUtil: scheduleSyncingChannel - Exception: " + e.getMessage()); + } } /** @@ -241,7 +246,12 @@ builder.setExtras(bundle); scheduler.cancel(getTriggeredJobIdForChannelId(channelId)); - scheduler.schedule(builder.build()); + + try { + scheduler.schedule(builder.build()); + } catch (IllegalStateException e) { + Log.w(TAG, "TvUtil: scheduleTriggeredSyncingProgramsForChannel - Exception: " + e.getMessage()); + } } /** @@ -271,7 +281,11 @@ JobInfo job = builder.build(); Log.d(TAG, "scheduleTimedSyncingProgramsForChannel: minperiod=" + job.getMinPeriodMillis()); - scheduler.schedule(job); + try { + scheduler.schedule(job); + } catch (IllegalStateException e) { + Log.w(TAG, "TvUtil: scheduleTimedSyncingProgramsForChannel - Exception: " + e.getMessage()); + } } public static int getTriggeredJobIdForChannelId(long channelId) diff -Nru kodi-20.1+git20230312.0705-289ec664e3/tools/buildsteps/windows/make-mingwlibs.bat kodi-20.2+git20230630.0528-5f418d0b13/tools/buildsteps/windows/make-mingwlibs.bat --- kodi-20.1+git20230312.0705-289ec664e3/tools/buildsteps/windows/make-mingwlibs.bat 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/tools/buildsteps/windows/make-mingwlibs.bat 2013-05-12 08:41:54.000000000 +0000 @@ -5,8 +5,9 @@ SET WORKDIR=%CD% POPD -REM recreates ffmpeg build dir in case it does not exist +REM recreates clean ffmpeg build dir SET BUILD_DIR=%WORKDIR%\project\BuildDependencies\build +IF EXIST %BUILD_DIR% rmdir %BUILD_DIR% /S /Q IF NOT EXIST %BUILD_DIR% mkdir %BUILD_DIR% SET PROMPTLEVEL=prompt diff -Nru kodi-20.1+git20230312.0705-289ec664e3/tools/buildsteps/windows/prepare-env.bat kodi-20.2+git20230630.0528-5f418d0b13/tools/buildsteps/windows/prepare-env.bat --- kodi-20.1+git20230312.0705-289ec664e3/tools/buildsteps/windows/prepare-env.bat 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/tools/buildsteps/windows/prepare-env.bat 2013-05-12 08:41:54.000000000 +0000 @@ -10,6 +10,9 @@ rem clean the BUILD_WIN32 at first to avoid problems with possible git files in there IF EXIST %WORKSPACE%\project\Win32BuildSetup\BUILD_WIN32 rmdir %WORKSPACE%\project\Win32BuildSetup\BUILD_WIN32 /S /Q +rem also clean 'build' dir used to build ffmpeg as git clean has trouble to remove some times +IF EXIST %WORKSPACE%\project\BuildDependencies\build rmdir %WORKSPACE%\project\BuildDependencies\build /S /Q + rem we assume git in path as this is a requirement rem git clean the untracked files and directories rem but keep the downloaded dependencies @@ -18,8 +21,3 @@ ECHO running %GIT_CLEAN_CMD% %GIT_CLEAN_CMD% - -REM 'build' dir is necessary to extract ffmpeg code -REM we prevents missing under certain circumstances (early creation) -SET BUILD_FFMPEG=%WORKSPACE%\project\BuildDependencies\build -IF NOT EXIST %BUILD_FFMPEG% mkdir %BUILD_FFMPEG% diff -Nru kodi-20.1+git20230312.0705-289ec664e3/tools/depends/native/TexturePacker/src/decoder/IDecoder.h kodi-20.2+git20230630.0528-5f418d0b13/tools/depends/native/TexturePacker/src/decoder/IDecoder.h --- kodi-20.1+git20230312.0705-289ec664e3/tools/depends/native/TexturePacker/src/decoder/IDecoder.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/tools/depends/native/TexturePacker/src/decoder/IDecoder.h 2013-05-12 08:41:54.000000000 +0000 @@ -20,6 +20,7 @@ #pragma once +#include #include #include diff -Nru kodi-20.1+git20230312.0705-289ec664e3/tools/depends/target/crossguid/003-add-cstdint-include.patch kodi-20.2+git20230630.0528-5f418d0b13/tools/depends/target/crossguid/003-add-cstdint-include.patch --- kodi-20.1+git20230312.0705-289ec664e3/tools/depends/target/crossguid/003-add-cstdint-include.patch 1970-01-01 00:00:00.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/tools/depends/target/crossguid/003-add-cstdint-include.patch 2013-05-12 08:41:54.000000000 +0000 @@ -0,0 +1,10 @@ +--- a/include/crossguid/guid.hpp ++++ b/include/crossguid/guid.hpp +@@ -36,6 +36,7 @@ THE SOFTWARE. + #include + #include + #include ++#include + + #define BEGIN_XG_NAMESPACE namespace xg { + #define END_XG_NAMESPACE } diff -Nru kodi-20.1+git20230312.0705-289ec664e3/tools/depends/target/crossguid/Makefile kodi-20.2+git20230630.0528-5f418d0b13/tools/depends/target/crossguid/Makefile --- kodi-20.1+git20230312.0705-289ec664e3/tools/depends/target/crossguid/Makefile 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/tools/depends/target/crossguid/Makefile 2013-05-12 08:41:54.000000000 +0000 @@ -45,6 +45,7 @@ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) cd $(PLATFORM); patch -p1 -i ../001-fix-unused-function.patch cd $(PLATFORM); patch -p1 -i ../002-disable-Wall-error.patch + cd $(PLATFORM); patch -p1 -i ../003-add-cstdint-include.patch cd $(PLATFORM)/build; $(CMAKE) $(CMAKE_OPTIONS) .. .installed-$(PLATFORM): $(PLATFORM) diff -Nru kodi-20.1+git20230312.0705-289ec664e3/tools/depends/target/waylandpp/001-fix-gcc13-build.patch kodi-20.2+git20230630.0528-5f418d0b13/tools/depends/target/waylandpp/001-fix-gcc13-build.patch --- kodi-20.1+git20230312.0705-289ec664e3/tools/depends/target/waylandpp/001-fix-gcc13-build.patch 1970-01-01 00:00:00.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/tools/depends/target/waylandpp/001-fix-gcc13-build.patch 2013-05-12 08:41:54.000000000 +0000 @@ -0,0 +1,28 @@ +--- a/include/wayland-client.hpp ++++ b/include/wayland-client.hpp +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include + #include + #include + +--- a/scanner/scanner.cpp ++++ b/scanner/scanner.cpp +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include "pugixml.hpp" + +@@ -928,6 +929,7 @@ + << "#include " << std::endl + << "#include " << std::endl + << "#include " << std::endl ++ << "#include " << std::endl + << std::endl + << "#include " << std::endl; diff -Nru kodi-20.1+git20230312.0705-289ec664e3/tools/depends/target/waylandpp/Makefile kodi-20.2+git20230630.0528-5f418d0b13/tools/depends/target/waylandpp/Makefile --- kodi-20.1+git20230312.0705-289ec664e3/tools/depends/target/waylandpp/Makefile 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/tools/depends/target/waylandpp/Makefile 2013-05-12 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ -include ../../Makefile.include -DEPS =Makefile ../../download-files.include +DEPS =Makefile ../../download-files.include 001-fix-gcc13-build.patch # lib name, version LIBNAME=waylandpp @@ -41,6 +41,7 @@ endif rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 -i ../001-fix-gcc13-build.patch mkdir -p $(BUILDDIR) cd $(BUILDDIR); $(CMAKE) $(CMAKE_OPTIONS) .. diff -Nru kodi-20.1+git20230312.0705-289ec664e3/tools/Linux/kodi.metainfo.xml.in kodi-20.2+git20230630.0528-5f418d0b13/tools/Linux/kodi.metainfo.xml.in --- kodi-20.1+git20230312.0705-289ec664e3/tools/Linux/kodi.metainfo.xml.in 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/tools/Linux/kodi.metainfo.xml.in 2013-05-12 08:41:54.000000000 +0000 @@ -78,6 +78,7 @@ + https://kodi.tv/article/kodi-20-2-nexus-release/ https://kodi.tv/article/kodi-20-1-nexus-release/ https://kodi.tv/article/kodi-20-0-nexus-release/ https://kodi.tv/article/kodi-nexus-rc-2/ diff -Nru kodi-20.1+git20230312.0705-289ec664e3/VERSION kodi-20.2+git20230630.0528-5f418d0b13/VERSION --- kodi-20.1+git20230312.0705-289ec664e3/VERSION 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/VERSION 2013-05-12 08:41:54.000000000 +0000 @@ -1 +1 @@ -289ec664e3 +5f418d0b13 diff -Nru kodi-20.1+git20230312.0705-289ec664e3/version.txt kodi-20.2+git20230630.0528-5f418d0b13/version.txt --- kodi-20.1+git20230312.0705-289ec664e3/version.txt 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/version.txt 2013-05-12 08:41:54.000000000 +0000 @@ -3,10 +3,10 @@ COPYRIGHT_YEARS 2005-2021 WEBSITE http://kodi.tv VERSION_MAJOR 20 -VERSION_MINOR 1 +VERSION_MINOR 2 VERSION_TAG -VERSION_CODE 20.1.0 -ADDON_API 20.1.0 +VERSION_CODE 20.2.0 +ADDON_API 20.2.0 ADDON_REPOS repository.xbmc.org|https://mirrors.kodi.tv APP_PACKAGE org.xbmc.kodi PACKAGE_IDENTITY XBMCFoundation.Kodi diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/addons/gui/skin/SkinTimerManager.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/addons/gui/skin/SkinTimerManager.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/addons/gui/skin/SkinTimerManager.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/addons/gui/skin/SkinTimerManager.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -73,7 +73,8 @@ startInfo = CServiceBroker::GetGUI()->GetInfoManager().Register( node->FirstChild("start")->FirstChild()->ValueStr()); // check if timer needs to be reset after start - if (node->Attribute("reset") && StringUtils::EqualsNoCase(node->Attribute("reset"), "true")) + if (node->FirstChildElement("start")->Attribute("reset") && + StringUtils::EqualsNoCase(node->FirstChildElement("start")->Attribute("reset"), "true")) { resetOnStart = true; } diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/addons/interfaces/Filesystem.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/addons/interfaces/Filesystem.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/addons/interfaces/Filesystem.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/addons/interfaces/Filesystem.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -167,7 +167,7 @@ } CFileItemList items; - return CDirectory::GetDirectory(url, items, "", DIR_FLAG_DEFAULTS); + return CDirectory::GetDirectory(url, items, "", DIR_FLAG_DEFAULTS | DIR_FLAG_BYPASS_CACHE); } bool Interface_Filesystem::create_directory(void* kodiBase, const char* path) @@ -193,7 +193,7 @@ return false; } - return CDirectory::Exists(path); + return CDirectory::Exists(path, false); } bool Interface_Filesystem::remove_directory(void* kodiBase, const char* path) @@ -208,7 +208,7 @@ // Empty directory CFileItemList fileItems; - CDirectory::GetDirectory(path, fileItems, "", DIR_FLAG_DEFAULTS); + CDirectory::GetDirectory(path, fileItems, "", DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_BYPASS_CACHE); for (int i = 0; i < fileItems.Size(); ++i) CFile::Delete(fileItems.Get(i)->GetPath()); @@ -260,7 +260,8 @@ } CFileItemList fileItems; - if (!CDirectory::GetDirectory(path, fileItems, mask, DIR_FLAG_NO_FILE_DIRS)) + if (!CDirectory::GetDirectory(path, fileItems, mask, + DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_BYPASS_CACHE)) return false; if (fileItems.Size() > 0) diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/application/Application.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/application/Application.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/application/Application.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/application/Application.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -1757,6 +1757,17 @@ } break; + case TMSG_UPDATE_PLAYER_ITEM: + { + std::unique_ptr item{static_cast(pMsg->lpVoid)}; + if (item) + { + m_itemCurrentFile->UpdateInfo(*item); + CServiceBroker::GetGUI()->GetInfoManager().UpdateCurrentItem(*m_itemCurrentFile); + } + } + break; + default: CLog::Log(LOGERROR, "{}: Unhandled threadmessage sent, {}", __FUNCTION__, msg); break; diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -13,50 +13,34 @@ #include #include -#define DTS_PREAMBLE_14BE 0x1FFFE800 -#define DTS_PREAMBLE_14LE 0xFF1F00E8 -#define DTS_PREAMBLE_16BE 0x7FFE8001 -#define DTS_PREAMBLE_16LE 0xFE7F0180 -#define DTS_PREAMBLE_HD 0x64582025 -#define DTS_PREAMBLE_XCH 0x5a5a5a5a -#define DTS_PREAMBLE_XXCH 0x47004a03 -#define DTS_PREAMBLE_X96K 0x1d95f262 -#define DTS_PREAMBLE_XBR 0x655e315e -#define DTS_PREAMBLE_LBR 0x0a801921 -#define DTS_PREAMBLE_XLL 0x41a29547 -#define DTS_SFREQ_COUNT 16 -#define MAX_EAC3_BLOCKS 6 +#define DTS_PREAMBLE_14BE 0x1FFFE800 +#define DTS_PREAMBLE_14LE 0xFF1F00E8 +#define DTS_PREAMBLE_16BE 0x7FFE8001 +#define DTS_PREAMBLE_16LE 0xFE7F0180 +#define DTS_PREAMBLE_HD 0x64582025 +#define DTS_PREAMBLE_XCH 0x5a5a5a5a +#define DTS_PREAMBLE_XXCH 0x47004a03 +#define DTS_PREAMBLE_X96K 0x1d95f262 +#define DTS_PREAMBLE_XBR 0x655e315e +#define DTS_PREAMBLE_LBR 0x0a801921 +#define DTS_PREAMBLE_XLL 0x41a29547 +#define DTS_SFREQ_COUNT 16 +#define MAX_EAC3_BLOCKS 6 #define UNKNOWN_DTS_EXTENSION 255 -static const uint16_t AC3Bitrates [] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640}; -static const uint16_t AC3FSCod [] = {48000, 44100, 32000, 0}; -static const uint8_t AC3BlkCod [] = {1, 2, 3, 6}; -static const uint8_t AC3Channels [] = {2, 1, 2, 3, 3, 4, 4, 5}; -static const uint8_t DTSChannels [] = {1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8}; -static const uint8_t THDChanMap [] = {2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1}; - -static const uint32_t DTSSampleRates[DTS_SFREQ_COUNT] = -{ - 0 , - 8000 , - 16000 , - 32000 , - 64000 , - 128000, - 11025 , - 22050 , - 44100 , - 88200 , - 176400, - 12000 , - 24000 , - 48000 , - 96000 , - 192000 -}; +static const uint16_t AC3Bitrates[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, + 192, 224, 256, 320, 384, 448, 512, 576, 640}; +static const uint16_t AC3FSCod[] = {48000, 44100, 32000, 0}; +static const uint8_t AC3BlkCod[] = {1, 2, 3, 6}; +static const uint8_t AC3Channels[] = {2, 1, 2, 3, 3, 4, 4, 5}; +static const uint8_t DTSChannels[] = {1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8}; +static const uint8_t THDChanMap[] = {2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1}; + +static const uint32_t DTSSampleRates[DTS_SFREQ_COUNT] = {0, 8000, 16000, 32000, 64000, 128000, + 11025, 22050, 44100, 88200, 176400, 12000, + 24000, 48000, 96000, 192000}; -CAEStreamParser::CAEStreamParser() : - m_syncFunc (&CAEStreamParser::DetectType) +CAEStreamParser::CAEStreamParser() : m_syncFunc(&CAEStreamParser::DetectType) { av_crc_init(m_crcTrueHD, 0, 16, 0x2D, sizeof(m_crcTrueHD)); } @@ -74,9 +58,7 @@ break; case STREAM_TYPE_TRUEHD: int rate; - if (m_sampleRate == 48000 || - m_sampleRate == 96000 || - m_sampleRate == 192000) + if (m_sampleRate == 48000 || m_sampleRate == 96000 || m_sampleRate == 192000) rate = 192000; else rate = 176400; @@ -120,7 +102,10 @@ m_hasSync = false; } -int CAEStreamParser::AddData(uint8_t *data, unsigned int size, uint8_t **buffer/* = NULL */, unsigned int *bufferSize/* = 0 */) +int CAEStreamParser::AddData(uint8_t* data, + unsigned int size, + uint8_t** buffer, + unsigned int* bufferSize) { if (size == 0) { @@ -154,7 +139,7 @@ unsigned int consumed = 0; unsigned int offset = 0; unsigned int room = sizeof(m_buffer) - m_bufferSize; - while(true) + while (true) { if (!size) { @@ -181,12 +166,12 @@ break; else { - /* lost sync */ + // lost sync m_syncFunc = &CAEStreamParser::DetectType; m_info.m_type = CAEStreamInfo::STREAM_TYPE_NULL; m_info.m_repeat = 1; - /* if the buffer is full, or the offset < the buffer size */ + // if the buffer is full, or the offset < the buffer size if (m_bufferSize == sizeof(m_buffer) || offset < m_bufferSize) { m_bufferSize -= offset; @@ -196,16 +181,16 @@ } } - /* if we got here, we acquired sync on the buffer */ + // if we got here, we acquired sync on the buffer - /* align the buffer */ + // align the buffer if (offset) { m_bufferSize -= offset; memmove(m_buffer, m_buffer + offset, m_bufferSize); } - /* bytes to skip until the next packet */ + // bytes to skip until the next packet m_skipBytes = std::max(0, (int)m_fsize - (int)m_bufferSize); if (m_skipBytes) { @@ -223,56 +208,52 @@ } } -void CAEStreamParser::GetPacket(uint8_t **buffer, unsigned int *bufferSize) +void CAEStreamParser::GetPacket(uint8_t** buffer, unsigned int* bufferSize) { - /* if the caller wants the packet */ + // if the caller wants the packet if (buffer) { - /* if it is dtsHD and we only want the core, just fetch that */ + // if it is dtsHD and we only want the core, just fetch that unsigned int size = m_fsize; if (m_info.m_type == CAEStreamInfo::STREAM_TYPE_DTSHD_CORE) size = m_coreSize; - /* make sure the buffer is allocated and big enough */ + // make sure the buffer is allocated and big enough if (!*buffer || !bufferSize || *bufferSize < size) { - delete[] *buffer; + delete[] * buffer; *buffer = new uint8_t[size]; } - /* copy the data into the buffer and update the size */ + // copy the data into the buffer and update the size memcpy(*buffer, m_buffer, size); if (bufferSize) *bufferSize = size; } - /* remove the parsed data from the buffer */ + // remove the parsed data from the buffer m_bufferSize -= m_fsize; memmove(m_buffer, m_buffer + m_fsize, m_bufferSize); m_fsize = 0; m_coreSize = 0; } -/* SYNC FUNCTIONS */ +// SYNC FUNCTIONS -/* - This function looks for sync words across the types in parallel, and only does an exhaustive - test if it finds a syncword. Once sync has been established, the relevant sync function sets - m_syncFunc to itself. This function will only be called again if total sync is lost, which - allows is to switch stream types on the fly much like a real receiver does. -*/ -unsigned int CAEStreamParser::DetectType(uint8_t *data, unsigned int size) +// This function looks for sync words across the types in parallel, and only does an exhaustive +// test if it finds a syncword. Once sync has been established, the relevant sync function sets +// m_syncFunc to itself. This function will only be called again if total sync is lost, which +// allows is to switch stream types on the fly much like a real receiver does. +unsigned int CAEStreamParser::DetectType(uint8_t* data, unsigned int size) { - unsigned int skipped = 0; + unsigned int skipped = 0; unsigned int possible = 0; while (size > 8) { - /* if it could be DTS */ + // if it could be DTS unsigned int header = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; - if (header == DTS_PREAMBLE_14LE || - header == DTS_PREAMBLE_14BE || - header == DTS_PREAMBLE_16LE || + if (header == DTS_PREAMBLE_14LE || header == DTS_PREAMBLE_14BE || header == DTS_PREAMBLE_16LE || header == DTS_PREAMBLE_16BE) { unsigned int skip = SyncDTS(data, size); @@ -282,7 +263,7 @@ possible = skipped; } - /* if it could be AC3 */ + // if it could be AC3 if (data[0] == 0x0b && data[1] == 0x77) { unsigned int skip = SyncAC3(data, size); @@ -292,7 +273,7 @@ possible = skipped; } - /* if it could be TrueHD */ + // if it could be TrueHD if (data[4] == 0xf8 && data[5] == 0x72 && data[6] == 0x6f && data[7] == 0xba) { unsigned int skip = SyncTrueHD(data, size); @@ -302,7 +283,7 @@ possible = skipped; } - /* move along one byte */ + // move along one byte --size; ++skipped; ++data; @@ -311,23 +292,26 @@ return possible ? possible : skipped; } -bool CAEStreamParser::TrySyncAC3(uint8_t *data, unsigned int size, bool resyncing, bool wantEAC3dependent) +bool CAEStreamParser::TrySyncAC3(uint8_t* data, + unsigned int size, + bool resyncing, + bool wantEAC3dependent) { if (size < 8) return false; - /* look for an ac3 sync word */ + // look for an ac3 sync word if (data[0] != 0x0b || data[1] != 0x77) return false; - uint8_t bsid = data[5] >> 3; + uint8_t bsid = data[5] >> 3; uint8_t acmod = data[6] >> 5; uint8_t lfeon; int8_t pos = 4; if ((acmod & 0x1) && (acmod != 0x1)) pos -= 2; - if (acmod & 0x4 ) + if (acmod & 0x4) pos -= 2; if (acmod == 0x2) pos -= 2; @@ -341,7 +325,7 @@ if (bsid <= 10) { - /* Normal AC-3 */ + // Normal AC-3 if (wantEAC3dependent) return false; @@ -351,41 +335,50 @@ if (fscod == 3 || frmsizecod > 37) return false; - /* get the details we need to check crc1 and framesize */ + // get the details we need to check crc1 and framesize unsigned int bitRate = AC3Bitrates[frmsizecod >> 1]; unsigned int framesize = 0; switch (fscod) { - case 0: framesize = bitRate * 2; break; - case 1: framesize = (320 * bitRate / 147 + (frmsizecod & 1 ? 1 : 0)); break; - case 2: framesize = bitRate * 4; break; + case 0: + framesize = bitRate * 2; + break; + case 1: + framesize = (320 * bitRate / 147 + (frmsizecod & 1 ? 1 : 0)); + break; + case 2: + framesize = bitRate * 4; + break; } m_fsize = framesize << 1; m_info.m_sampleRate = AC3FSCod[fscod]; - /* dont do extensive testing if we have not lost sync */ + // dont do extensive testing if we have not lost sync if (m_info.m_type == CAEStreamInfo::STREAM_TYPE_AC3 && !resyncing) return true; - /* this may be the main stream of EAC3 */ + // this may be the main stream of EAC3 unsigned int fsizeMain = m_fsize; unsigned int reqBytes = fsizeMain + 8; - if (size < reqBytes) { - /* not enough data to check for E-AC3 dependent frame, request more */ + if (size < reqBytes) + { + // not enough data to check for E-AC3 dependent frame, request more m_needBytes = reqBytes; m_fsize = 0; - /* no need to resync => return true */ + // no need to resync => return true return true; } - if (TrySyncAC3(data + fsizeMain, size - fsizeMain, resyncing, /*wantEAC3dependent*/ true)) { - /* concatenate the main and dependent frames */ + m_info.m_ac3FrameSize = fsizeMain; + if (TrySyncAC3(data + fsizeMain, size - fsizeMain, resyncing, true)) + { + // concatenate the main and dependent frames m_fsize += fsizeMain; return true; } unsigned int crc_size; - /* if we have enough data, validate the entire packet, else try to validate crc2 (5/8 of the packet) */ + // if we have enough data, validate the entire packet, else try to validate crc2 (5/8 of the packet) if (framesize <= size) crc_size = framesize - 1; else @@ -395,12 +388,12 @@ if (av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, &data[2], crc_size * 2)) return false; - /* if we get here, we can sync */ + // if we get here, we can sync m_hasSync = true; m_info.m_channels = AC3Channels[acmod] + lfeon; m_syncFunc = &CAEStreamParser::SyncAC3; m_info.m_type = CAEStreamInfo::STREAM_TYPE_AC3; - m_info.m_ac3FrameSize = m_fsize; + m_info.m_ac3FrameSize += m_fsize; m_info.m_repeat = 1; CLog::Log(LOGINFO, "CAEStreamParser::TrySyncAC3 - AC3 stream detected ({} channels, {}Hz)", @@ -446,6 +439,28 @@ m_fsize = framesize << 1; m_info.m_repeat = MAX_EAC3_BLOCKS / blocks; + // EAC3 can have a dependent stream too + if (!wantEAC3dependent) + { + unsigned int fsizeMain = m_fsize; + unsigned int reqBytes = fsizeMain + 8; + if (size < reqBytes) + { + // not enough data to check for E-AC3 dependent frame, request more + m_needBytes = reqBytes; + m_fsize = 0; + // no need to resync => return true + return true; + } + m_info.m_ac3FrameSize = fsizeMain; + if (TrySyncAC3(data + fsizeMain, size - fsizeMain, resyncing, true)) + { + // concatenate the main and dependent frames + m_fsize += fsizeMain; + return true; + } + } + if (m_info.m_type == CAEStreamInfo::STREAM_TYPE_EAC3 && m_hasSync && !resyncing) return true; @@ -454,7 +469,7 @@ m_info.m_channels = AC3Channels[acmod] + lfeon; m_syncFunc = &CAEStreamParser::SyncAC3; m_info.m_type = CAEStreamInfo::STREAM_TYPE_EAC3; - m_info.m_ac3FrameSize = m_fsize; + m_info.m_ac3FrameSize += m_fsize; CLog::Log(LOGINFO, "CAEStreamParser::TrySyncAC3 - E-AC3 stream detected ({} channels, {}Hz)", m_info.m_channels, m_info.m_sampleRate); @@ -462,14 +477,14 @@ } } -unsigned int CAEStreamParser::SyncAC3(uint8_t *data, unsigned int size) +unsigned int CAEStreamParser::SyncAC3(uint8_t* data, unsigned int size) { unsigned int skip = 0; for (; size - skip > 7; ++skip, ++data) { bool resyncing = (skip != 0); - if (TrySyncAC3(data, size - skip, resyncing, /*wantEAC3dependent*/ false)) + if (TrySyncAC3(data, size - skip, resyncing, false)) return skip; } @@ -479,7 +494,7 @@ return skip; } -unsigned int CAEStreamParser::SyncDTS(uint8_t *data, unsigned int size) +unsigned int CAEStreamParser::SyncDTS(uint8_t* data, unsigned int size) { if (size < 13) { @@ -504,7 +519,7 @@ switch (header) { - /* 14bit BE */ + // 14bit BE case DTS_PREAMBLE_14BE: if (data[4] != 0x07 || (data[5] & 0xf0) != 0xf0) continue; @@ -516,11 +531,11 @@ ext_type = ((data[11] & 0xe) >> 1); sfreq = data[9] & 0xF; lfe = (data[12] & 0x18) >> 3; - m_info.m_dataIsLE = false; + m_info.m_dataIsLE = false; bits = 14; break; - /* 14bit LE */ + // 14bit LE case DTS_PREAMBLE_14LE: if (data[5] != 0x07 || (data[4] & 0xf0) != 0xf0) continue; @@ -536,7 +551,7 @@ bits = 14; break; - /* 16bit BE */ + // 16bit BE case DTS_PREAMBLE_16BE: dtsBlocks = (((data[4] & 0x1) << 7) | ((data[5] & 0xFC) >> 2)) + 1; m_fsize = (((((data[5] & 0x3) << 8) | data[6]) << 4) | ((data[7] & 0xF0) >> 4)) + 1; @@ -550,7 +565,7 @@ bits = 16; break; - /* 16bit LE */ + // 16bit LE case DTS_PREAMBLE_16LE: dtsBlocks = (((data[5] & 0x1) << 7) | ((data[4] & 0xFC) >> 2)) + 1; m_fsize = (((((data[4] & 0x3) << 8) | data[7]) << 4) | ((data[6] & 0xF0) >> 4)) + 1; @@ -571,7 +586,7 @@ if (sfreq == 0 || sfreq >= DTS_SFREQ_COUNT) continue; - /* make sure the framesize is sane */ + // make sure the framesize is sane if (m_fsize < 96 || m_fsize > 16384) continue; @@ -579,9 +594,15 @@ CAEStreamInfo::DataType dataType; switch (dtsBlocks << 5) { - case 512 : dataType = CAEStreamInfo::STREAM_TYPE_DTS_512 ; break; - case 1024: dataType = CAEStreamInfo::STREAM_TYPE_DTS_1024; break; - case 2048: dataType = CAEStreamInfo::STREAM_TYPE_DTS_2048; break; + case 512: + dataType = CAEStreamInfo::STREAM_TYPE_DTS_512; + break; + case 1024: + dataType = CAEStreamInfo::STREAM_TYPE_DTS_1024; + break; + case 2048: + dataType = CAEStreamInfo::STREAM_TYPE_DTS_2048; + break; default: invalid = true; break; @@ -590,31 +611,36 @@ if (invalid) continue; - /* adjust the fsize for 14 bit streams */ + // adjust the fsize for 14 bit streams if (bits == 14) m_fsize = m_fsize / 14 * 16; - /* we need enough data to check for DTS-HD */ + // we need enough data to check for DTS-HD if (size - skip < m_fsize + 10) { - /* we can assume DTS sync at this point */ - m_syncFunc = &CAEStreamParser::SyncDTS; + // we can assume DTS sync at this point + m_syncFunc = &CAEStreamParser::SyncDTS; m_needBytes = m_fsize + 10; - m_fsize = 0; + m_fsize = 0; return skip; } - /* look for DTS-HD */ - hd_sync = (data[m_fsize] << 24) | (data[m_fsize + 1] << 16) | (data[m_fsize + 2] << 8) | data[m_fsize + 3]; + // look for DTS-HD + hd_sync = (data[m_fsize] << 24) | (data[m_fsize + 1] << 16) | (data[m_fsize + 2] << 8) | + data[m_fsize + 3]; if (hd_sync == DTS_PREAMBLE_HD) { int hd_size; bool blownup = (data[m_fsize + 5] & 0x20) != 0; if (blownup) - hd_size = (((data[m_fsize + 6] & 0x01) << 19) | (data[m_fsize + 7] << 11) | (data[m_fsize + 8] << 3) | ((data[m_fsize + 9] & 0xe0) >> 5)) + 1; + hd_size = (((data[m_fsize + 6] & 0x01) << 19) | (data[m_fsize + 7] << 11) | + (data[m_fsize + 8] << 3) | ((data[m_fsize + 9] & 0xe0) >> 5)) + + 1; else - hd_size = (((data[m_fsize + 6] & 0x1f) << 11) | (data[m_fsize + 7] << 3) | ((data[m_fsize + 8] & 0xe0) >> 5)) + 1; + hd_size = (((data[m_fsize + 6] & 0x1f) << 11) | (data[m_fsize + 7] << 3) | + ((data[m_fsize + 8] & 0xe0) >> 5)) + + 1; int header_size; if (blownup) @@ -622,17 +648,16 @@ else header_size = (((data[m_fsize + 5] & 0x1f) << 3) | ((data[m_fsize + 6] & 0xe0) >> 5)) + 1; - hd_sync = data[m_fsize + header_size] << 24 | data[m_fsize + header_size + 1] << 16 | data[m_fsize + header_size + 2] << 8 | data[m_fsize + header_size + 3]; + hd_sync = data[m_fsize + header_size] << 24 | data[m_fsize + header_size + 1] << 16 | + data[m_fsize + header_size + 2] << 8 | data[m_fsize + header_size + 3]; - /* set the type according to core or not */ + // set the type according to core or not if (m_coreOnly) dataType = CAEStreamInfo::STREAM_TYPE_DTSHD_CORE; else if (hd_sync == DTS_PREAMBLE_XLL) dataType = CAEStreamInfo::STREAM_TYPE_DTSHD_MA; - else if (hd_sync == DTS_PREAMBLE_XCH || - hd_sync == DTS_PREAMBLE_XXCH || - hd_sync == DTS_PREAMBLE_X96K || - hd_sync == DTS_PREAMBLE_XBR || + else if (hd_sync == DTS_PREAMBLE_XCH || hd_sync == DTS_PREAMBLE_XXCH || + hd_sync == DTS_PREAMBLE_X96K || hd_sync == DTS_PREAMBLE_XBR || hd_sync == DTS_PREAMBLE_LBR) dataType = CAEStreamInfo::STREAM_TYPE_DTSHD; else @@ -643,7 +668,8 @@ } unsigned int sampleRate = DTSSampleRates[sfreq]; - if (!m_hasSync || skip || dataType != m_info.m_type || sampleRate != m_info.m_sampleRate || dtsBlocks != m_dtsBlocks) + if (!m_hasSync || skip || dataType != m_info.m_type || sampleRate != m_info.m_sampleRate || + dtsBlocks != m_dtsBlocks) { m_hasSync = true; m_info.m_type = dataType; @@ -655,7 +681,7 @@ if (dataType == CAEStreamInfo::STREAM_TYPE_DTSHD_MA) { - m_info.m_channels += 2; /* FIXME: this needs to be read out, not sure how to do that yet */ + m_info.m_channels += 2; // FIXME: this needs to be read out, not sure how to do that yet m_info.m_dtsPeriod = (192000 * (8 >> 1)) * (m_dtsBlocks << 5) / m_info.m_sampleRate; } else if (dataType == CAEStreamInfo::STREAM_TYPE_DTSHD) @@ -664,7 +690,8 @@ } else { - m_info.m_dtsPeriod = (m_info.m_sampleRate * (2 >> 1)) * (m_dtsBlocks << 5) / m_info.m_sampleRate; + m_info.m_dtsPeriod = + (m_info.m_sampleRate * (2 >> 1)) * (m_dtsBlocks << 5) / m_info.m_sampleRate; } std::string type; @@ -713,7 +740,7 @@ return skip; } - /* lost sync */ + // lost sync CLog::Log(LOGINFO, "CAEStreamParser::SyncDTS - DTS sync lost"); m_hasSync = false; return skip; @@ -727,28 +754,28 @@ return channels; } -unsigned int CAEStreamParser::SyncTrueHD(uint8_t *data, unsigned int size) +unsigned int CAEStreamParser::SyncTrueHD(uint8_t* data, unsigned int size) { unsigned int left = size; unsigned int skip = 0; - /* if MLP */ + // if MLP for (; left; ++skip, ++data, --left) { - /* if we dont have sync and there is less the 8 bytes, then break out */ + // if we dont have sync and there is less the 8 bytes, then break out if (!m_hasSync && left < 8) return size; - /* if its a major audio unit */ - uint16_t length = ((data[0] & 0x0F) << 8 | data[1]) << 1; + // if its a major audio unit + uint16_t length = ((data[0] & 0x0F) << 8 | data[1]) << 1; uint32_t syncword = ((((data[4] << 8 | data[5]) << 8) | data[6]) << 8) | data[7]; if (syncword == 0xf8726fba) { - /* we need 32 bytes to sync on a master audio unit */ + // we need 32 bytes to sync on a master audio unit if (left < 32) return skip; - /* get the rate and ensure its valid */ + // get the rate and ensure its valid int rate = (data[8] & 0xf0) >> 4; if (rate == 0xF) continue; @@ -756,7 +783,7 @@ unsigned int major_sync_size = 28; if (data[29] & 1) { - /* extension(s) present, look up count */ + // extension(s) present, look up count int extension_count = data[30] >> 4; major_sync_size += 2 + extension_count * 2; } @@ -764,17 +791,17 @@ if (left < 4 + major_sync_size) return skip; - /* verify the crc of the audio unit */ + // verify the crc of the audio unit uint16_t crc = av_crc(m_crcTrueHD, 0, data + 4, major_sync_size - 4); crc ^= (data[4 + major_sync_size - 3] << 8) | data[4 + major_sync_size - 4]; if (((data[4 + major_sync_size - 1] << 8) | data[4 + major_sync_size - 2]) != crc) continue; - /* get the sample rate and substreams, we have a valid master audio unit */ + // get the sample rate and substreams, we have a valid master audio unit m_info.m_sampleRate = (rate & 0x8 ? 44100 : 48000) << (rate & 0x7); m_substreams = (data[20] & 0xF0) >> 4; - /* get the number of encoded channels */ + // get the number of encoded channels uint16_t channel_map = ((data[10] & 0x1F) << 8) | data[11]; if (!channel_map) channel_map = (data[9] << 1) | (data[10] >> 7); @@ -794,16 +821,16 @@ } else { - /* we cant sink to a subframe until we have the information from a master audio unit */ + // we cant sink to a subframe until we have the information from a master audio unit if (!m_hasSync) continue; - /* if there is not enough data left to verify the packet, just return the skip amount */ + // if there is not enough data left to verify the packet, just return the skip amount if (left < (unsigned int)m_substreams * 4) return skip; - /* verify the parity */ - int p = 0; + // verify the parity + int p = 0; uint8_t check = 0; for (int i = -1; i < m_substreams; ++i) { @@ -816,11 +843,11 @@ } } - /* if the parity nibble does not match */ + // if the parity nibble does not match if ((((check >> 4) ^ check) & 0xF) != 0xF) { - /* lost sync */ - m_hasSync = false; + // lost sync + m_hasSync = false; CLog::Log(LOGINFO, "CAEStreamParser::SyncTrueHD - Sync Lost"); continue; } @@ -832,8 +859,7 @@ } } - /* lost sync */ - m_hasSync = false; + // lost sync + m_hasSync = false; return skip; } - diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/cheevos/Cheevos.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/cheevos/Cheevos.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/cheevos/Cheevos.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/cheevos/Cheevos.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -8,11 +8,15 @@ #include "Cheevos.h" +#include "FileItem.h" +#include "ServiceBroker.h" #include "URL.h" #include "filesystem/CurlFile.h" #include "filesystem/File.h" #include "games/addons/GameClient.h" #include "games/addons/cheevos/GameClientCheevos.h" +#include "games/tags/GameInfoTag.h" +#include "messaging/ApplicationMessenger.h" #include "utils/JSONVariantParser.h" #include "utils/URIUtils.h" #include "utils/Variant.h" @@ -29,8 +33,13 @@ constexpr auto GAME_ID = "GameID"; constexpr auto PATCH_DATA = "PatchData"; constexpr auto RICH_PRESENCE = "RichPresencePatch"; +constexpr auto GAME_TITLE = "Title"; +constexpr auto PUBLISHER = "Publisher"; +constexpr auto DEVELOPER = "Developer"; +constexpr auto GENRE = "Genre"; +constexpr auto CONSOLE_NAME = "ConsoleName"; -constexpr int RESPORNSE_SIZE = 64; +constexpr int RESPONSE_SIZE = 64; } // namespace CCheevos::CCheevos(GAME::CGameClient* gameClient, @@ -75,8 +84,8 @@ response.CURLCreate(requestURL); response.CURLOpen(0); - char responseStr[RESPORNSE_SIZE]; - response.ReadString(responseStr, RESPORNSE_SIZE); + char responseStr[RESPONSE_SIZE]; + response.ReadString(responseStr, RESPONSE_SIZE); response.Close(); @@ -108,6 +117,18 @@ m_richPresenceScript = data[PATCH_DATA][RICH_PRESENCE].asString(); m_richPresenceLoaded = true; + std::unique_ptr file{std::make_unique()}; + + GAME::CGameInfoTag& tag = *file->GetGameInfoTag(); + tag.SetTitle(data[PATCH_DATA][GAME_TITLE].asString()); + tag.SetPublisher(data[PATCH_DATA][PUBLISHER].asString()); + tag.SetDeveloper(data[PATCH_DATA][DEVELOPER].asString()); + tag.SetGenres({data[PATCH_DATA][GENRE].asString()}); + tag.SetPlatform(data[PATCH_DATA][CONSOLE_NAME].asString()); + + CServiceBroker::GetAppMessenger()->PostMsg(TMSG_UPDATE_PLAYER_ITEM, -1, -1, + static_cast(file.release())); + return true; } diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/cheevos/Cheevos.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/cheevos/Cheevos.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/cheevos/Cheevos.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/cheevos/Cheevos.h 2013-05-12 08:41:54.000000000 +0000 @@ -10,6 +10,7 @@ #include "RConsoleIDs.h" +#include #include #include diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/rendering/RPRenderManager.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/rendering/RPRenderManager.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/rendering/RPRenderManager.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/rendering/RPRenderManager.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -123,35 +123,56 @@ return true; } -std::vector CRPRenderManager::GetVideoBuffers(unsigned int width, - unsigned int height) +bool CRPRenderManager::GetVideoBuffer(unsigned int width, + unsigned int height, + VideoStreamBuffer& buffer) { - std::vector buffers; + // Clear any previous pending buffers + for (IRenderBuffer* buffer : m_pendingBuffers) + buffer->Release(); + m_pendingBuffers.clear(); if (m_bFlush || m_state != RENDER_STATE::CONFIGURED) - return buffers; + return false; - // Get buffers from visible renderers - for (IRenderBufferPool* bufferPool : m_processInfo.GetBufferManager().GetBufferPools()) - { - if (!bufferPool->HasVisibleRenderer()) - continue; + // We should do our best to get a valid render buffer. If we return false, + // the game add-on will likely allocate its own memory. + IRenderBuffer* renderBuffer = nullptr; + + auto bufferPools = m_processInfo.GetBufferManager().GetBufferPools(); + + std::sort(bufferPools.begin(), bufferPools.end(), + [](const IRenderBufferPool* lhs, const IRenderBufferPool* rhs) { + // Prefer buffer pools with a visible renderer + if (lhs->HasVisibleRenderer() && !rhs->HasVisibleRenderer()) + return true; + if (!lhs->HasVisibleRenderer() && rhs->HasVisibleRenderer()) + return false; - IRenderBuffer* renderBuffer = bufferPool->GetBuffer(width, height); + //! @todo De-prioritize buffer pools with write-only or unaligned memory + + return false; + }); + + for (IRenderBufferPool* bufferPool : bufferPools) + { + renderBuffer = bufferPool->GetBuffer(width, height); if (renderBuffer != nullptr) - m_pendingBuffers.emplace_back(renderBuffer); + break; else CLog::Log(LOGDEBUG, "RetroPlayer[RENDER]: Unable to get video buffer for frame"); } - for (IRenderBuffer* renderBuffer : m_pendingBuffers) - { - buffers.emplace_back(VideoStreamBuffer{ - renderBuffer->GetFormat(), renderBuffer->GetMemory(), renderBuffer->GetFrameSize(), - renderBuffer->GetMemoryAccess(), renderBuffer->GetMemoryAlignment()}); - } + if (renderBuffer == nullptr) + return false; + + buffer = VideoStreamBuffer{renderBuffer->GetFormat(), renderBuffer->GetMemory(), + renderBuffer->GetFrameSize(), renderBuffer->GetMemoryAccess(), + renderBuffer->GetMemoryAlignment()}; - return buffers; + m_pendingBuffers.emplace_back(std::move(renderBuffer)); + + return true; } void CRPRenderManager::AddFrame(const uint8_t* data, diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/rendering/RPRenderManager.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/rendering/RPRenderManager.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/rendering/RPRenderManager.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/rendering/RPRenderManager.h 2013-05-12 08:41:54.000000000 +0000 @@ -93,7 +93,7 @@ unsigned int maxWidth, unsigned int maxHeight, float pixelAspectRatio); - std::vector GetVideoBuffers(unsigned int width, unsigned int height); + bool GetVideoBuffer(unsigned int width, unsigned int height, VideoStreamBuffer& buffer); void AddFrame(const uint8_t* data, size_t size, unsigned int width, diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/RetroPlayer.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/RetroPlayer.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/RetroPlayer.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/RetroPlayer.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -9,6 +9,7 @@ #include "RetroPlayer.h" #include "FileItem.h" +#include "GUIInfoManager.h" #include "RetroPlayerAutoSave.h" #include "RetroPlayerInput.h" #include "ServiceBroker.h" @@ -42,6 +43,7 @@ #include "guilib/WindowIDs.h" #include "input/actions/Action.h" #include "input/actions/ActionIDs.h" +#include "interfaces/AnnouncementManager.h" #include "messaging/ApplicationMessenger.h" #include "utils/JobManager.h" #include "utils/StringUtils.h" diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/savestates/SavestateFlatBuffer.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/savestates/SavestateFlatBuffer.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/savestates/SavestateFlatBuffer.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/savestates/SavestateFlatBuffer.h 2013-05-12 08:41:54.000000000 +0000 @@ -14,11 +14,6 @@ #include -namespace flatbuffers -{ -class FlatBufferBuilder; -} - namespace KODI { namespace RETRO diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -13,8 +13,6 @@ #include "cores/RetroPlayer/rendering/RenderTranslator.h" #include "utils/log.h" -#include - using namespace KODI; using namespace RETRO; @@ -74,33 +72,7 @@ VideoStreamBuffer& videoBuffer = static_cast(buffer); if (m_bOpen) - { - m_buffers = m_renderManager.GetVideoBuffers(width, height); - - std::sort(m_buffers.begin(), m_buffers.end(), - [](const VideoStreamBuffer& lhs, const VideoStreamBuffer& rhs) { - // Prefer read-write over write only - if (lhs.access == DataAccess::READ_WRITE && rhs.access != DataAccess::READ_WRITE) - return true; - if (lhs.access != DataAccess::READ_WRITE && rhs.access == DataAccess::READ_WRITE) - return false; - - // Prefer aligned over unaligned - if (lhs.alignment == DataAlignment::DATA_ALIGNED && - rhs.alignment != DataAlignment::DATA_ALIGNED) - return true; - if (lhs.alignment != DataAlignment::DATA_ALIGNED && - rhs.alignment == DataAlignment::DATA_ALIGNED) - return false; - - return false; - }); - - //! @todo This comment was in the original code - //! @todo Handle multiple buffers - if (!m_buffers.empty()) - videoBuffer = m_buffers.at(0); - } + return m_renderManager.GetVideoBuffer(width, height, videoBuffer); return false; } @@ -130,8 +102,6 @@ m_renderManager.AddFrame(videoPacket.data, videoPacket.size, videoPacket.width, videoPacket.height, orientationDegCCW); } - - m_buffers.clear(); } void CRetroPlayerVideo::CloseStream() diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h 2013-05-12 08:41:54.000000000 +0000 @@ -107,7 +107,6 @@ // Stream properties bool m_bOpen = false; - std::vector m_buffers; }; } // namespace RETRO } // namespace KODI diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -274,7 +274,41 @@ if (m_hints.cryptoSession) { m_mime = "audio/raw"; - m_codec = std::shared_ptr(new CJNIMediaCodec(CJNIMediaCodec::createDecoderByType(m_mime))); + + // Workaround for old Android devices + // Prefer the Google raw decoder over the MediaTek one + const std::vector codecInfos = + CJNIMediaCodecList(CJNIMediaCodecList::REGULAR_CODECS).getCodecInfos(); + + bool mtk_raw_decoder = false; + bool google_raw_decoder = false; + + for (const CJNIMediaCodecInfo& codec_info : codecInfos) + { + if (codec_info.isEncoder()) + continue; + + if (codec_info.getName() == "OMX.MTK.AUDIO.DECODER.RAW") + mtk_raw_decoder = true; + if (codec_info.getName() == "OMX.google.raw.decoder") + google_raw_decoder = true; + } + + if (CJNIBase::GetSDKVersion() <= 27 && mtk_raw_decoder && google_raw_decoder) + { + CLog::Log(LOGDEBUG, "CDVDAudioCodecAndroidMediaCodec::Open Prefer the Google raw decoder " + "over the MediaTek one"); + m_codec = std::shared_ptr( + new CJNIMediaCodec(CJNIMediaCodec::createByCodecName("OMX.google.raw.decoder"))); + } + else + { + CLog::Log( + LOGDEBUG, + "CDVDAudioCodecAndroidMediaCodec::Open Use the raw decoder proposed by the platform"); + m_codec = std::shared_ptr( + new CJNIMediaCodec(CJNIMediaCodec::createDecoderByType(m_mime))); + } if (xbmc_jnienv()->ExceptionCheck()) { xbmc_jnienv()->ExceptionDescribe(); diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecText.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecText.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecText.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecText.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -18,6 +18,15 @@ #include +namespace +{ +// Subtitle packets reaching the decoder may not have the stop PTS value, +// the stop value can be taken from the start PTS of the next subtitle. +// Otherwise we fallback to a default of 20 secs duration. This is only +// applied if the subtitle packets have 0 duration (stop > start). +constexpr double DEFAULT_DURATION = 20.0 * static_cast(DVD_TIME_BASE); +} // namespace + CDVDOverlayCodecText::CDVDOverlayCodecText() : CDVDOverlayCodec("Text Subtitle Decoder") { m_pOverlay = nullptr; @@ -83,7 +92,23 @@ { TagConv.ConvertLine(text); TagConv.CloseTag(text); - AddSubtitle(text, PTSStartTime, PTSStopTime); + + // similar to CC text, if the subtitle duration is invalid (stop > start) + // we might want to assume the stop time will be set by the next received + // packet + if (PTSStopTime < PTSStartTime) + { + if (m_changePrevStopTime) + { + ChangeSubtitleStopTime(m_prevSubId, PTSStartTime); + m_changePrevStopTime = false; + } + + PTSStopTime = PTSStartTime + DEFAULT_DURATION; + m_changePrevStopTime = true; + } + + m_prevSubId = AddSubtitle(text, PTSStartTime, PTSStopTime); } else CLog::Log(LOGERROR, "{} - Failed to initialize tag converter", __FUNCTION__); diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecText.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecText.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecText.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecText.h 2013-05-12 08:41:54.000000000 +0000 @@ -37,5 +37,7 @@ void Dispose() override; CDVDOverlay* m_pOverlay; CDVDStreamInfo m_hints; + int m_prevSubId{-1}; + bool m_changePrevStopTime{false}; AVCodecID m_codecId{AV_CODEC_ID_NONE}; }; diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/OverlayCodecWebVTT.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/OverlayCodecWebVTT.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/OverlayCodecWebVTT.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/OverlayCodecWebVTT.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -80,7 +80,11 @@ m_webvttHandler.Reset(); - m_webvttHandler.SetPeriodStart(pPacket->m_ptsOffsetCorrection); + // WebVTT subtitles has no relation with packet PTS then if + // a period/chapter change happens (e.g. HLS streaming) VP can detect a discontinuity + // and adjust the packet PTS by substracting the pts offset correction value, + // so here we have to adjust WebVTT subtitles PTS by substracting it at same way + m_webvttHandler.SetPeriodStart(pPacket->m_ptsOffsetCorrection * -1); if (m_isISOFormat) { diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -525,6 +525,8 @@ if (!m_audioSink.Create(audioframe, m_streaminfo.codec, m_synctype == SYNC_RESAMPLE)) CLog::Log(LOGERROR, "{} - failed to create audio renderer", __FUNCTION__); + m_prevsynctype = -1; + if (m_syncState == IDVDStreamPlayer::SYNC_INSYNC) m_audioSink.Resume(); } diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -15,6 +15,7 @@ #include "utils/TimeUtils.h" #include "utils/log.h" +#include #include #include diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.h 2013-05-12 08:41:54.000000000 +0000 @@ -12,6 +12,7 @@ #include #endif +#include #include extern "C" diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VaapiEGL.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VaapiEGL.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VaapiEGL.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VaapiEGL.h 2013-05-12 08:41:54.000000000 +0000 @@ -9,6 +9,7 @@ #pragma once #include +#include #if defined(HAS_GL) // always define GL_GLEXT_PROTOTYPES before include gl headers diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h 2013-05-12 08:41:54.000000000 +0000 @@ -196,7 +196,7 @@ double pts; EFIELDSYNC presentfield; EPRESENTMETHOD presentmethod; - } m_Queue[NUM_BUFFERS]; + } m_Queue[NUM_BUFFERS]{}; std::deque m_free; std::deque m_queued; diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererShaders.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererShaders.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererShaders.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererShaders.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -437,7 +437,6 @@ int srcLines[3]; videoBuffer->GetPlanes(bufData); videoBuffer->GetStrides(srcLines); - std::vector> tasks; for (unsigned plane = 0; plane < m_viewCount; ++plane) { @@ -451,35 +450,23 @@ int dstLine = mapping.RowPitch; int height = plane ? m_height >> 1 : m_height; - auto task = Concurrency::create_task([src, dst, srcLine, dstLine, height]() + if (srcLine == dstLine) { - if (srcLine == dstLine) - { - memcpy(dst, src, srcLine * height); - } - else + memcpy(dst, src, srcLine * height); + } + else + { + uint8_t* s = src; + uint8_t* d = dst; + for (int i = 0; i < height; ++i) { - uint8_t* s = src; - uint8_t* d = dst; - for (int i = 0; i < height; ++i) - { - memcpy(d, s, std::min(srcLine, dstLine)); - d += dstLine; - s += srcLine; - } + memcpy(d, s, std::min(srcLine, dstLine)); + d += dstLine; + s += srcLine; } - }); - tasks.push_back(task); + } } - // event based await is required on WinRT because - // blocking WinRT STA threads with task.wait() isn't allowed - auto sync = std::make_shared(); - when_all(tasks.begin(), tasks.end()).then([&sync]() { - sync->set(); - }); - sync->wait(); - for (unsigned plane = 0; plane < m_viewCount; ++plane) if (!m_textures[plane].UnlockRect(0)) {} diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/GUIInfoManager.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/GUIInfoManager.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/GUIInfoManager.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/GUIInfoManager.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -15,6 +15,8 @@ #include "application/ApplicationComponents.h" #include "application/ApplicationPlayer.h" #include "cores/DataCacheCore.h" +#include "filesystem/File.h" +#include "games/tags/GameInfoTag.h" #include "guilib/guiinfo/GUIInfo.h" #include "guilib/guiinfo/GUIInfoHelper.h" #include "guilib/guiinfo/GUIInfoLabels.h" @@ -11327,6 +11329,14 @@ return nullptr; } + +const KODI::GAME::CGameInfoTag* CGUIInfoManager::GetCurrentGameTag() const +{ + if (m_currentFile->HasGameInfoTag()) + return m_currentFile->GetGameInfoTag(); + + return nullptr; +} int CGUIInfoManager::RegisterSkinVariableString(const CSkinVariableString* info) { diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/GUIInfoManager.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/GUIInfoManager.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/GUIInfoManager.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/GUIInfoManager.h 2013-05-12 08:41:54.000000000 +0000 @@ -28,6 +28,10 @@ namespace KODI { +namespace GAME +{ +class CGameInfoTag; +} namespace GUILIB { namespace GUIINFO @@ -131,6 +135,9 @@ // Current video stuff const CVideoInfoTag* GetCurrentMovieTag() const; + // Current game stuff + const KODI::GAME::CGameInfoTag* GetCurrentGameTag() const; + void UpdateAVInfo(); int RegisterSkinVariableString(const INFO::CSkinVariableString* info); diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/interfaces/legacy/ListItem.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/interfaces/legacy/ListItem.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/interfaces/legacy/ListItem.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/interfaces/legacy/ListItem.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -901,17 +901,13 @@ xbmc::InfoTagPicture* ListItem::getPictureInfoTag() { XBMCAddonUtils::GuiLock lock(languageHook, m_offscreen); - if (item->HasPictureInfoTag()) - return new xbmc::InfoTagPicture(item->GetPictureInfoTag(), m_offscreen); - return new xbmc::InfoTagPicture(); + return new xbmc::InfoTagPicture(item->GetPictureInfoTag(), m_offscreen); } xbmc::InfoTagGame* ListItem::getGameInfoTag() { XBMCAddonUtils::GuiLock lock(languageHook, m_offscreen); - if (item->HasGameInfoTag()) - return new xbmc::InfoTagGame(item->GetGameInfoTag(), m_offscreen); - return new xbmc::InfoTagGame(); + return new xbmc::InfoTagGame(item->GetGameInfoTag(), m_offscreen); } std::vector ListItem::getStringArray(const InfoLabelValue& alt, diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/interfaces/legacy/Player.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/interfaces/legacy/Player.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/interfaces/legacy/Player.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/interfaces/legacy/Player.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -356,6 +356,12 @@ return getAppPlayer()->IsPlayingRDS(); } + bool Player::isPlayingGame() + { + XBMC_TRACE; + return getAppPlayer()->IsPlayingGame(); + } + bool Player::isExternalPlayer() { XBMC_TRACE; @@ -417,6 +423,20 @@ CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg); } + InfoTagGame* Player::getGameInfoTag() + { + XBMC_TRACE; + if (!getAppPlayer()->IsPlayingGame()) + throw PlayerException("Kodi is not playing any game file"); + + const KODI::GAME::CGameInfoTag* game = + CServiceBroker::GetGUI()->GetInfoManager().GetCurrentGameTag(); + if (game) + return new InfoTagGame(game); + + return new InfoTagGame(); + } + InfoTagRadioRDS* Player::getRadioRDSInfoTag() { XBMC_TRACE; diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/interfaces/legacy/Player.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/interfaces/legacy/Player.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/interfaces/legacy/Player.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/interfaces/legacy/Player.h 2013-05-12 08:41:54.000000000 +0000 @@ -12,6 +12,7 @@ #include "AddonString.h" #include "Alternative.h" #include "Exception.h" +#include "InfoTagGame.h" #include "InfoTagMusic.h" #include "InfoTagRadioRDS.h" #include "InfoTagVideo.h" @@ -426,6 +427,22 @@ #ifdef DOXYGEN_SHOULD_USE_THIS /// /// \ingroup python_Player + /// @brief \python_func{ isPlayingGame() } + /// Check for playing game. + /// + /// @return True if kodi is playing a game + /// + ///------------------------------------------------------------------------ + /// @python_v20 New function added. + /// + isPlayingGame(); +#else + bool isPlayingGame(); +#endif + +#ifdef DOXYGEN_SHOULD_USE_THIS + /// + /// \ingroup python_Player /// @brief \python_func{ isExternalPlayer() } /// Check for external player. /// @@ -623,6 +640,25 @@ void updateInfoTag(const XBMCAddon::xbmcgui::ListItem* item); #endif +#ifdef DOXYGEN_SHOULD_USE_THIS + /// + /// \ingroup python_Player + /// @brief \python_func{ getGameInfoTag() } + /// To get game info tag. + /// + /// Returns the GameInfoTag of the current playing game. + /// + /// @return Game info tag + /// @throws Exception If player is not playing a file or current + /// file is not a game file. + /// + ///------------------------------------------------------------------------ + /// @python_v20 New function added. + /// + getGameInfoTag(); +#else + InfoTagGame* getGameInfoTag(); +#endif #ifdef DOXYGEN_SHOULD_USE_THIS /// diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/interfaces/python/PythonInvoker.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/interfaces/python/PythonInvoker.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/interfaces/python/PythonInvoker.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/interfaces/python/PythonInvoker.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -226,29 +226,30 @@ } PyObject* sysPath = PySys_GetObject("path"); - Py_ssize_t listSize = PyList_Size(sysPath); - if (listSize > 0) - CLog::Log(LOGDEBUG, "CPythonInvoker({}): default python path:", GetId()); + std::for_each(pythonPath.crbegin(), pythonPath.crend(), + [&sysPath](const auto& path) + { + PyObject* pyPath = PyUnicode_FromString(path.c_str()); + PyList_Insert(sysPath, 0, pyPath); - for (Py_ssize_t index = 0; index < listSize; index++) - { - PyObject* pyPath = PyList_GetItem(sysPath, index); + Py_DECREF(pyPath); + }); - CLog::Log(LOGDEBUG, "CPythonInvoker({}): {}", GetId(), PyUnicode_AsUTF8(pyPath)); - } + CLog::Log(LOGDEBUG, "CPythonInvoker({}): full python path:", GetId()); - if (!pythonPath.empty()) - CLog::Log(LOGDEBUG, "CPythonInvoker({}): adding path:", GetId()); + Py_ssize_t pathListSize = PyList_Size(sysPath); - for (const auto& path : pythonPath) + for (Py_ssize_t index = 0; index < pathListSize; index++) { - PyObject* pyPath = PyUnicode_FromString(path.c_str()); - PyList_Append(sysPath, pyPath); + if (index == 0 && !pythonPath.empty()) + CLog::Log(LOGDEBUG, "CPythonInvoker({}): custom python path:", GetId()); - CLog::Log(LOGDEBUG, "CPythonInvoker({}): {}", GetId(), PyUnicode_AsUTF8(pyPath)); + if (index == static_cast(pythonPath.size())) + CLog::Log(LOGDEBUG, "CPythonInvoker({}): default python path:", GetId()); - Py_DECREF(pyPath); + PyObject* pyPath = PyList_GetItem(sysPath, index); + CLog::Log(LOGDEBUG, "CPythonInvoker({}): {}", GetId(), PyUnicode_AsUTF8(pyPath)); } { // set the m_threadState to this new interp diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/messaging/ApplicationMessenger.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/messaging/ApplicationMessenger.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/messaging/ApplicationMessenger.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/messaging/ApplicationMessenger.h 2013-05-12 08:41:54.000000000 +0000 @@ -83,6 +83,9 @@ #define TMSG_RENDERER_UNINIT TMSG_MASK_APPLICATION + 32 #define TMSG_EVENT TMSG_MASK_APPLICATION + 33 +/// @brief Called from the player when its current item is updated +#define TMSG_UPDATE_PLAYER_ITEM TMSG_MASK_APPLICATION + 35 + #define TMSG_GUI_INFOLABEL TMSG_MASK_GUIINFOMANAGER + 0 #define TMSG_GUI_INFOBOOL TMSG_MASK_GUIINFOMANAGER + 1 #define TMSG_UPDATE_CURRENT_ITEM TMSG_MASK_GUIINFOMANAGER + 2 diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/network/upnp/UPnPInternal.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/network/upnp/UPnPInternal.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/network/upnp/UPnPInternal.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/network/upnp/UPnPInternal.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -59,6 +59,12 @@ // so we only match the extension of the "fake" content type "sup", "idx"}; +// Map defining extensions for mimetypes not available in Platinum mimetype map +// or that the application wants to override. These definitions take precedence +// over all other possible mime type definitions. +constexpr NPT_HttpFileRequestHandler_DefaultFileTypeMapEntry kodiPlatinumMimeTypeExtensions[] = { + {"m2ts", "video/vnd.dlna.mpeg-tts"}}; + /*---------------------------------------------------------------------- | GetClientQuirks +---------------------------------------------------------------------*/ @@ -141,15 +147,32 @@ NPT_String mime; - /* We always use Platinum mime type first - as it is defined to map extension to DLNA compliant mime type - or custom according to context (who asked for it) */ - if (!ext.IsEmpty()) { + if (!ext.IsEmpty()) + { + /* We look first to our extensions/overrides of libplatinum mimetypes. If not found, fallback to + Platinum definitions. + */ + const auto kodiOverrideMimeType = std::find_if( + std::begin(kodiPlatinumMimeTypeExtensions), std::end(kodiPlatinumMimeTypeExtensions), + [&](const auto& mimeTypeEntry) { return mimeTypeEntry.extension == ext; }); + if (kodiOverrideMimeType != std::end(kodiPlatinumMimeTypeExtensions)) + { + mime = kodiOverrideMimeType->mime_type; + } + else + { + /* Give priority to Platinum mime types as they are defined to map extension to DLNA compliant mime types + or custom types according to context (who asked for it) + */ mime = PLT_MimeType::GetMimeTypeFromExtension(ext, context); - if (mime == "application/octet-stream") mime = ""; + if (mime == "application/octet-stream") + { + mime = ""; + } + } } - /* if Platinum couldn't map it, default to XBMC mapping */ + /* if Platinum couldn't map it, default to Kodi internal mapping */ if (mime.IsEmpty()) { NPT_String mime = item.GetMimeType().c_str(); if (mime == "application/octet-stream") mime = ""; diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/pictures/Picture.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pictures/Picture.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/pictures/Picture.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pictures/Picture.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -257,10 +257,11 @@ if (ScaleImage(pixels, width, height, pitch, AV_PIX_FMT_BGRA, (uint8_t*)buffer, dest_width, dest_height, stride, AV_PIX_FMT_BGRA, scalingAlgorithm)) { - if (!orientation || OrientateImage(buffer, dest_width, dest_height, orientation)) + if (!orientation || + OrientateImage(buffer, dest_width, dest_height, orientation, dest_width_aligned)) { success = CreateThumbnailFromSurface((unsigned char*)buffer, dest_width, dest_height, - stride, dest); + dest_width_aligned * 4, dest); } } delete[] buffer; @@ -312,7 +313,9 @@ texture->GetPitch(), AV_PIX_FMT_BGRA, (uint8_t*)scaled, width, height, width * 4, AV_PIX_FMT_BGRA)) { - if (!texture->GetOrientation() || OrientateImage(scaled, width, height, texture->GetOrientation())) + unsigned int stridePixels{width}; + if (!texture->GetOrientation() || + OrientateImage(scaled, width, height, texture->GetOrientation(), stridePixels)) { success = true; // Flag that we at least had one successful image processed // drop into the texture @@ -324,7 +327,7 @@ { memcpy(dest, src, width*4); dest += imageRes; - src += width; + src += stridePixels; } } } @@ -379,32 +382,36 @@ return false; } -bool CPicture::OrientateImage(uint32_t *&pixels, unsigned int &width, unsigned int &height, int orientation) +bool CPicture::OrientateImage(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + int orientation, + unsigned int& stridePixels) { // ideas for speeding these functions up: http://cgit.freedesktop.org/pixman/tree/pixman/pixman-fast-path.c bool out = false; switch (orientation) { case 1: - out = FlipHorizontal(pixels, width, height); + out = FlipHorizontal(pixels, width, height, stridePixels); break; case 2: - out = Rotate180CCW(pixels, width, height); + out = Rotate180CCW(pixels, width, height, stridePixels); break; case 3: - out = FlipVertical(pixels, width, height); + out = FlipVertical(pixels, width, height, stridePixels); break; case 4: - out = Transpose(pixels, width, height); + out = Transpose(pixels, width, height, stridePixels); break; case 5: - out = Rotate270CCW(pixels, width, height); + out = Rotate270CCW(pixels, width, height, stridePixels); break; case 6: - out = TransposeOffAxis(pixels, width, height); + out = TransposeOffAxis(pixels, width, height, stridePixels); break; case 7: - out = Rotate90CCW(pixels, width, height); + out = Rotate90CCW(pixels, width, height, stridePixels); break; default: CLog::Log(LOGERROR, "Unknown orientation {}", orientation); @@ -415,12 +422,13 @@ bool CPicture::FlipHorizontal(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height) + const unsigned int& height, + const unsigned int& stridePixels) { // this can be done in-place easily enough for (unsigned int y = 0; y < height; ++y) { - uint32_t *line = pixels + y * width; + uint32_t* line = pixels + y * stridePixels; for (unsigned int x = 0; x < width / 2; ++x) std::swap(line[x], line[width - 1 - x]); } @@ -429,13 +437,14 @@ bool CPicture::FlipVertical(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height) + const unsigned int& height, + const unsigned int& stridePixels) { // this can be done in-place easily enough for (unsigned int y = 0; y < height / 2; ++y) { - uint32_t *line1 = pixels + y * width; - uint32_t *line2 = pixels + (height - 1 - y) * width; + uint32_t* line1 = pixels + y * stridePixels; + uint32_t* line2 = pixels + (height - 1 - y) * stridePixels; for (unsigned int x = 0; x < width; ++x) std::swap(*line1++, *line2++); } @@ -444,26 +453,30 @@ bool CPicture::Rotate180CCW(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height) + const unsigned int& height, + const unsigned int& stridePixels) { // this can be done in-place easily enough for (unsigned int y = 0; y < height / 2; ++y) { - uint32_t *line1 = pixels + y * width; - uint32_t *line2 = pixels + (height - 1 - y) * width + width - 1; + uint32_t* line1 = pixels + y * stridePixels; + uint32_t* line2 = pixels + (height - 1 - y) * stridePixels + width - 1; for (unsigned int x = 0; x < width; ++x) std::swap(*line1++, *line2--); } if (height % 2) { // height is odd, so flip the middle row as well - uint32_t *line = pixels + (height - 1)/2 * width; + uint32_t* line = pixels + (height - 1) / 2 * stridePixels; for (unsigned int x = 0; x < width / 2; ++x) std::swap(line[x], line[width - 1 - x]); } return true; } -bool CPicture::Rotate90CCW(uint32_t *&pixels, unsigned int &width, unsigned int &height) +bool CPicture::Rotate90CCW(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels) { uint32_t *dest = new uint32_t[width * height * 4]; if (dest) @@ -476,18 +489,22 @@ for (unsigned int x = 0; x < d_width; x++) { *dst++ = *src; - src += width; + src += stridePixels; } } delete[] pixels; pixels = dest; std::swap(width, height); + stridePixels = width; return true; } return false; } -bool CPicture::Rotate270CCW(uint32_t *&pixels, unsigned int &width, unsigned int &height) +bool CPicture::Rotate270CCW(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels) { uint32_t *dest = new uint32_t[width * height * 4]; if (!dest) @@ -496,22 +513,27 @@ unsigned int d_height = width, d_width = height; for (unsigned int y = 0; y < d_height; y++) { - const uint32_t *src = pixels + width * (d_width - 1) + y; // y-th col from left, starting at bottom - uint32_t *dst = dest + d_width * y; // y-th row from top, starting at left + const uint32_t* src = + pixels + stridePixels * (d_width - 1) + y; // y-th col from left, starting at bottom + uint32_t* dst = dest + d_width * y; // y-th row from top, starting at left for (unsigned int x = 0; x < d_width; x++) { *dst++ = *src; - src -= width; + src -= stridePixels; } } delete[] pixels; pixels = dest; std::swap(width, height); + stridePixels = width; return true; } -bool CPicture::Transpose(uint32_t *&pixels, unsigned int &width, unsigned int &height) +bool CPicture::Transpose(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels) { uint32_t *dest = new uint32_t[width * height * 4]; if (!dest) @@ -525,17 +547,21 @@ for (unsigned int x = 0; x < d_width; x++) { *dst++ = *src; - src += width; + src += stridePixels; } } delete[] pixels; pixels = dest; std::swap(width, height); + stridePixels = width; return true; } -bool CPicture::TransposeOffAxis(uint32_t *&pixels, unsigned int &width, unsigned int &height) +bool CPicture::TransposeOffAxis(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels) { uint32_t *dest = new uint32_t[width * height * 4]; if (!dest) @@ -544,17 +570,19 @@ unsigned int d_height = width, d_width = height; for (unsigned int y = 0; y < d_height; y++) { - const uint32_t *src = pixels + width * (d_width - 1) + (d_height - 1 - y); // y-th col from right, starting at bottom + const uint32_t* src = pixels + stridePixels * (d_width - 1) + + (d_height - 1 - y); // y-th col from right, starting at bottom uint32_t *dst = dest + d_width * y; // y-th row, starting at left for (unsigned int x = 0; x < d_width; x++) { *dst++ = *src; - src -= width; + src -= stridePixels; } } delete[] pixels; pixels = dest; std::swap(width, height); + stridePixels = width; return true; } diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/pictures/Picture.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pictures/Picture.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/pictures/Picture.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pictures/Picture.h 2013-05-12 08:41:54.000000000 +0000 @@ -11,6 +11,8 @@ #include "pictures/PictureScalingAlgorithm.h" #include "utils/Job.h" +#include +#include #include #include @@ -77,21 +79,40 @@ CPictureScalingAlgorithm::Algorithm scalingAlgorithm = CPictureScalingAlgorithm::NoAlgorithm); private: - static bool OrientateImage(uint32_t *&pixels, unsigned int &width, unsigned int &height, int orientation); + static bool OrientateImage(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + int orientation, + unsigned int& stridePixels); static bool FlipHorizontal(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height); + const unsigned int& height, + const unsigned int& stridePixels); static bool FlipVertical(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height); - static bool Rotate90CCW(uint32_t *&pixels, unsigned int &width, unsigned int &height); - static bool Rotate270CCW(uint32_t *&pixels, unsigned int &width, unsigned int &height); + const unsigned int& height, + const unsigned int& stridePixels); + static bool Rotate90CCW(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels); + static bool Rotate270CCW(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels); static bool Rotate180CCW(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height); - static bool Transpose(uint32_t *&pixels, unsigned int &width, unsigned int &height); - static bool TransposeOffAxis(uint32_t *&pixels, unsigned int &width, unsigned int &height); + const unsigned int& height, + const unsigned int& stridePixels); + static bool Transpose(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& width_aligned); + static bool TransposeOffAxis(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels); }; //this class calls CreateThumbnailFromSurface in a CJob, so a png file can be written without halting the render thread diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/darwin/ios/Info.plist.in kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/darwin/ios/Info.plist.in --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/darwin/ios/Info.plist.in 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/darwin/ios/Info.plist.in 2013-05-12 08:41:54.000000000 +0000 @@ -405,5 +405,9 @@ + NSSpeechRecognitionUsageDescription + Translate speech to text in virtual keyboard dialog + NSMicrophoneUsageDescription + Used for speech recognition diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/darwin/osx/Info.plist.in kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/darwin/osx/Info.plist.in --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/darwin/osx/Info.plist.in 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/darwin/osx/Info.plist.in 2013-05-12 08:41:54.000000000 +0000 @@ -32,5 +32,9 @@ @CMAKE_OSX_DEPLOYMENT_TARGET@ CFBundleSignature @APP_NAME@ + NSSpeechRecognitionUsageDescription + Translate speech to text in virtual keyboard dialog + NSMicrophoneUsageDescription + Used for speech recognition Binary files /tmp/tmp0494x1gt/MJX0YBSrAp/kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/darwin/tvos/Assets.xcassets/LaunchImage.launchimage/splash.jpg and /tmp/tmp0494x1gt/sM8lXWDhZ_/kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/darwin/tvos/Assets.xcassets/LaunchImage.launchimage/splash.jpg differ diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/Filesystem.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/Filesystem.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/Filesystem.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/Filesystem.h 2013-05-12 08:41:54.000000000 +0000 @@ -8,6 +8,7 @@ #pragma once +#include #include #include namespace KODI diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/linux/CPUInfoLinux.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/linux/CPUInfoLinux.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/linux/CPUInfoLinux.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/linux/CPUInfoLinux.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -13,6 +13,7 @@ #include "platform/linux/SysfsPath.h" +#include #include #include #include @@ -71,23 +72,23 @@ { CSysfsPath machinePath{"/sys/bus/soc/devices/soc0/machine"}; if (machinePath.Exists()) - m_cpuHardware = machinePath.Get(); + m_cpuHardware = machinePath.Get().value_or(""); CSysfsPath familyPath{"/sys/bus/soc/devices/soc0/family"}; if (familyPath.Exists()) - m_cpuSoC = familyPath.Get(); + m_cpuSoC = familyPath.Get().value_or(""); CSysfsPath socPath{"/sys/bus/soc/devices/soc0/soc_id"}; if (socPath.Exists()) - m_cpuSoC += " " + socPath.Get(); + m_cpuSoC += " " + socPath.Get().value_or(""); CSysfsPath revisionPath{"/sys/bus/soc/devices/soc0/revision"}; if (revisionPath.Exists()) - m_cpuRevision += revisionPath.Get(); + m_cpuRevision = revisionPath.Get().value_or(""); CSysfsPath serialPath{"/sys/bus/soc/devices/soc0/serial_number"}; if (serialPath.Exists()) - m_cpuSerial += serialPath.Get(); + m_cpuSerial = serialPath.Get().value_or(""); const std::string freqStr{"/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"}; CSysfsPath freqPath{freqStr}; @@ -109,7 +110,7 @@ auto name = path.Get(); - if (name.empty()) + if (!name.has_value()) continue; for (const auto& module : modules) @@ -353,8 +354,8 @@ if (m_freqPath.empty()) return 0; - CSysfsPath path{m_freqPath}; - return path.Get() / 1000.0f; + auto freq = CSysfsPath(m_freqPath).Get(); + return freq.has_value() ? *freq / 1000.0f : 0.0f; } bool CCPUInfoLinux::GetTemperature(CTemperature& temperature) @@ -365,8 +366,11 @@ if (m_tempPath.empty()) return false; - CSysfsPath path{m_tempPath}; - double value = path.Get() / 1000.0; + auto temp = CSysfsPath(m_tempPath).Get(); + if (!temp.has_value()) + return false; + + double value = *temp / 1000.0; temperature = CTemperature::CreateFromCelsius(value); temperature.SetValid(true); diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/linux/SysfsPath.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/linux/SysfsPath.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/linux/SysfsPath.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/linux/SysfsPath.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -8,6 +8,8 @@ #include "SysfsPath.h" +#include + bool CSysfsPath::Exists() { std::ifstream file(m_path); @@ -19,19 +21,27 @@ } template<> -std::string CSysfsPath::Get() +std::optional CSysfsPath::Get() { - std::ifstream file(m_path); + try + { + std::ifstream file(m_path); - std::string value; + std::string value; - std::getline(file, value); + std::getline(file, value); - if (file.bad()) + if (file.bad()) + { + CLog::LogF(LOGERROR, "error reading from '{}'", m_path); + return std::nullopt; + } + + return value; + } + catch (const std::exception& e) { - CLog::LogF(LOGERROR, "error reading from '{}'", m_path); - throw std::runtime_error("error reading from " + m_path); + CLog::LogF(LOGERROR, "exception reading from '{}': {}", m_path, e.what()); + return std::nullopt; } - - return value; } diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/linux/SysfsPath.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/linux/SysfsPath.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/linux/SysfsPath.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/linux/SysfsPath.h 2013-05-12 08:41:54.000000000 +0000 @@ -10,7 +10,9 @@ #include "utils/log.h" +#include #include +#include #include class CSysfsPath @@ -23,21 +25,29 @@ bool Exists(); template - T Get() + std::optional Get() { - std::ifstream file(m_path); + try + { + std::ifstream file(m_path); + + T value; - T value; + file >> value; - file >> value; + if (file.bad()) + { + CLog::LogF(LOGERROR, "error reading from '{}'", m_path); + return std::nullopt; + } - if (file.bad()) + return value; + } + catch (const std::exception& e) { - CLog::LogF(LOGERROR, "error reading from '{}'", m_path); - throw std::runtime_error("error reading from " + m_path); + CLog::LogF(LOGERROR, "exception reading from '{}': {}", m_path, e.what()); + return std::nullopt; } - - return value; } private: @@ -45,4 +55,4 @@ }; template<> -std::string CSysfsPath::Get(); +std::optional CSysfsPath::Get(); diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/posix/Filesystem.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/posix/Filesystem.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/posix/Filesystem.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/posix/Filesystem.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -19,9 +19,11 @@ #include #endif +#include #include #include #include + #include namespace KODI diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/win32/threads/ThreadImplWin.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/win32/threads/ThreadImplWin.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/platform/win32/threads/ThreadImplWin.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/platform/win32/threads/ThreadImplWin.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -67,14 +67,14 @@ { DWORD dwType; // must be 0x1000 LPCSTR szName; // pointer to name (in same addr space) - DWORD dwThreadID; // thread ID (-1 caller thread) - DWORD dwFlags; // reserved for future use, most be zero + DWORD dwThreadID; // thread ID (-1 = caller thread) + DWORD dwFlags; // reserved for future use, must be zero } info; #pragma pack(pop) info.dwType = 0x1000; info.szName = name.c_str(); - info.dwThreadID = reinterpret_cast(m_handle); + info.dwThreadID = GetThreadId(static_cast(m_handle)); info.dwFlags = 0; __try diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -445,6 +445,23 @@ { m_timerType = it->second; + // reset certain settings to the defaults of the new timer type + + if (m_timerType->SupportsPriority()) + m_iPriority = m_timerType->GetPriorityDefault(); + + if (m_timerType->SupportsLifetime()) + m_iLifetime = m_timerType->GetLifetimeDefault(); + + if (m_timerType->SupportsMaxRecordings()) + m_iMaxRecordings = m_timerType->GetMaxRecordingsDefault(); + + if (m_timerType->SupportsRecordingGroup()) + m_iRecordingGroup = m_timerType->GetRecordingGroupDefault(); + + if (m_timerType->SupportsRecordOnlyNewEpisodes()) + m_iPreventDupEpisodes = m_timerType->GetPreventDuplicateEpisodesDefault(); + if (m_timerType->IsTimerRule() && (m_iWeekdays == PVR_WEEKDAY_ALLDAYS)) SetButtonLabels(); // update "Any day" vs. "Every day" } diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/pvr/PVRManager.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pvr/PVRManager.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/pvr/PVRManager.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pvr/PVRManager.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -754,6 +754,9 @@ return false; } + // reinit playbackstate as new client may provide new last opened group / last played channel + m_playbackState->ReInit(); + PublishEvent(PVREvent::ClientsInvalidated); return true; } diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -29,6 +29,7 @@ #include "utils/URIUtils.h" #include "video/VideoLibraryQueue.h" #include "video/VideoUtils.h" +#include "video/windows/GUIWindowVideoBase.h" #include "video/windows/GUIWindowVideoNav.h" #include @@ -385,7 +386,7 @@ { if (m_database.Open()) { - CGUIWindowVideoNav::LoadVideoInfo(files, m_database, false); + CGUIWindowVideoBase::LoadVideoInfo(files, m_database, false); m_database.Close(); } m_thumbLoader.Load(files); diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/pvr/windows/GUIWindowPVRSearch.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pvr/windows/GUIWindowPVRSearch.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/pvr/windows/GUIWindowPVRSearch.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/pvr/windows/GUIWindowPVRSearch.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -441,7 +441,8 @@ else if (result == CGUIDialogPVRGuideSearch::Result::SAVE) { CServiceBroker::GetPVRManager().EpgContainer().PersistSavedSearch(*tmpSearchFilter); - searchFilter->SetDatabaseId(tmpSearchFilter->GetDatabaseId()); + if (searchFilter) + searchFilter->SetDatabaseId(tmpSearchFilter->GetDatabaseId()); const CPVREpgSearchPath path(m_vecItems->GetPath()); if (path.IsValid() && path.IsSearchRoot()) diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/rendering/dx/DeviceResources.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/rendering/dx/DeviceResources.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/rendering/dx/DeviceResources.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/rendering/dx/DeviceResources.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -708,6 +708,7 @@ ComPtr dxgiDevice; hr = m_d3dDevice.As(&dxgiDevice); CHECK_ERR(); dxgiDevice->SetMaximumFrameLatency(1); + m_usedSwapChain = false; } CLog::LogF(LOGDEBUG, "end resize buffers."); @@ -935,6 +936,7 @@ bool DX::DeviceResources::Begin() { HRESULT hr = m_swapChain->Present(0, DXGI_PRESENT_TEST); + m_usedSwapChain = true; // If the device was removed either by a disconnection or a driver upgrade, we // must recreate all device resources. @@ -966,6 +968,7 @@ // frames that will never be displayed to the screen. DXGI_PRESENT_PARAMETERS parameters = {}; HRESULT hr = m_swapChain->Present1(1, 0, ¶meters); + m_usedSwapChain = true; // If the device was removed either by a disconnection or a driver upgrade, we // must recreate all device resources. @@ -1270,6 +1273,18 @@ if (SUCCEEDED(m_swapChain.As(&swapChain3))) { + // Set the color space on a new swap chain - not mandated by MS documentation but needed + // at least for some AMD, at least up to Adrenalin 23.4.3 / Windows driver 31.0.14043.7000 + if (m_usedSwapChain && + m_IsTransferPQ != (colorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)) + { + // Temporary release, can't hold references during swap chain re-creation + swapChain3 = nullptr; + DestroySwapChain(); + CreateWindowSizeDependentResources(); + m_swapChain.As(&swapChain3); + } + if (SUCCEEDED(swapChain3->SetColorSpace1(colorSpace))) { m_IsTransferPQ = (colorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020); diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/rendering/dx/DeviceResources.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/rendering/dx/DeviceResources.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/rendering/dx/DeviceResources.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/rendering/dx/DeviceResources.h 2013-05-12 08:41:54.000000000 +0000 @@ -183,5 +183,6 @@ bool m_IsTransferPQ; bool m_NV12SharedTexturesSupport{false}; bool m_DXVA2SharedDecoderSurfaces{false}; + bool m_usedSwapChain{false}; }; } diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/settings/SettingConditions.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/settings/SettingConditions.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/settings/SettingConditions.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/settings/SettingConditions.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -102,14 +102,6 @@ return CServiceBroker::GetPeripherals().SupportsFeature(PERIPHERALS::FEATURE_POWER_OFF); } -bool IsFullscreen(const std::string& condition, - const std::string& value, - const SettingConstPtr& setting, - void* data) -{ - return CServiceBroker::GetWinSystem()->IsFullScreen(); -} - bool IsHDRDisplay(const std::string& condition, const std::string& value, const SettingConstPtr& setting, @@ -447,7 +439,6 @@ m_complexConditions.emplace("hasrumblefeature", HasRumbleFeature); m_complexConditions.emplace("hasrumblecontroller", HasRumbleController); m_complexConditions.emplace("haspowerofffeature", HasPowerOffFeature); - m_complexConditions.emplace("isfullscreen", IsFullscreen); m_complexConditions.emplace("ishdrdisplay", IsHDRDisplay); m_complexConditions.emplace("ismasteruser", IsMasterUser); m_complexConditions.emplace("hassubtitlesfontextensions", HasSubtitlesFontExtensions); diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/CharArrayParser.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/CharArrayParser.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/CharArrayParser.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/CharArrayParser.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -10,6 +10,7 @@ #include "utils/log.h" +#include #include void CCharArrayParser::Reset() diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/CharArrayParser.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/CharArrayParser.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/CharArrayParser.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/CharArrayParser.h 2013-05-12 08:41:54.000000000 +0000 @@ -8,6 +8,7 @@ #pragma once +#include #include /*! diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/CSSUtils.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/CSSUtils.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/CSSUtils.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/CSSUtils.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -8,6 +8,7 @@ #include "CSSUtils.h" +#include #include namespace diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/DRMHelpers.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/DRMHelpers.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/DRMHelpers.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/DRMHelpers.h 2013-05-12 08:41:54.000000000 +0000 @@ -8,6 +8,7 @@ #pragma once +#include #include namespace DRMHELPERS diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/FontUtils.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/FontUtils.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/FontUtils.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/FontUtils.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -25,6 +25,61 @@ using namespace XFILE; +namespace +{ +// \brief Get font family from SFNT table entries +std::string GetFamilyNameFromSfnt(FT_Face face) +{ + std::string familyName; + + for (FT_UInt index = 0; index < FT_Get_Sfnt_Name_Count(face); ++index) + { + FT_SfntName name; + if (FT_Get_Sfnt_Name(face, index, &name) != 0) + { + CLog::LogF(LOGWARNING, "Failed to get SFNT name at index {}", index); + continue; + } + + // Get the unicode font family name (format-specific interface) + // In properties there may be one or more font family names encoded for each platform. + // NOTE: we give preference to MS/APPLE platform data, then fallback to MAC + // because has been found some fonts that provide names not convertible MAC text to UTF8 + if (name.name_id == TT_NAME_ID_FONT_FAMILY) + { + const std::string nameEnc{reinterpret_cast(name.string), name.string_len}; + + if (name.platform_id == TT_PLATFORM_MICROSOFT || + name.platform_id == TT_PLATFORM_APPLE_UNICODE) + { + if (name.language_id != TT_MAC_LANGID_ENGLISH && + name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES && + name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM) + continue; + + if (CCharsetConverter::utf16BEtoUTF8(nameEnc, familyName)) + break; // Stop here to prefer the name given with this platform + else + CLog::LogF(LOGERROR, "Failed to convert the font name string encoded as \"UTF-16BE\""); + } + else if (name.platform_id == TT_PLATFORM_MACINTOSH && familyName.empty()) + { + if (name.language_id != TT_MAC_LANGID_ENGLISH || name.encoding_id != TT_MAC_ID_ROMAN) + continue; + + if (!CCharsetConverter::MacintoshToUTF8(nameEnc, familyName)) + CLog::LogF(LOGERROR, "Failed to convert the font name string encoded as \"macintosh\""); + } + else + { + CLog::LogF(LOGERROR, "Unsupported font SFNT name platform \"{}\"", name.platform_id); + } + } + } + return familyName; +} +} // unnamed namespace + std::string UTILS::FONT::GetFontFamily(std::vector& buffer) { FT_Library m_library{nullptr}; @@ -41,48 +96,15 @@ if (FT_New_Memory_Face(m_library, reinterpret_cast(buffer.data()), buffer.size(), 0, &face) == 0) { - // Get SFNT table entries to get font properties - for (FT_UInt index = 0; index < FT_Get_Sfnt_Name_Count(face); index++) - { - FT_SfntName name; - if (FT_Get_Sfnt_Name(face, index, &name) != 0) - { - CLog::LogF(LOGWARNING, "Failed to get SFNT name at index {}", index); - continue; - } - - // Get the unicode font family name (format-specific interface) - // In properties there may be one or more font family names encoded for - // each platform, we take the first available converting it to UTF-8 - if (name.name_id == TT_NAME_ID_FONT_FAMILY) - { - const std::string nameEnc{reinterpret_cast(name.string), name.string_len}; - - if (name.platform_id == TT_PLATFORM_MICROSOFT || - name.platform_id == TT_PLATFORM_APPLE_UNICODE) - { - if (!CCharsetConverter::utf16BEtoUTF8(nameEnc, familyName)) - CLog::LogF(LOGERROR, "Failed to convert the font name string encoded as \"UTF-16BE\""); - } - else if (name.platform_id == TT_PLATFORM_MACINTOSH) - { - if (!CCharsetConverter::MacintoshToUTF8(nameEnc, familyName)) - CLog::LogF(LOGERROR, "Failed to convert the font name string encoded as \"macintosh\""); - } - else - { - CLog::LogF(LOGERROR, "Unsupported font SFNT name platform \"{}\"", name.platform_id); - } - if (!familyName.empty()) - break; - } - } + familyName = GetFamilyNameFromSfnt(face); if (familyName.empty()) { CLog::LogF(LOGWARNING, "Failed to get the unicode family name for \"{}\", fallback to ASCII", face->family_name); // ASCII font family name may differ from the unicode one, use this as fallback only familyName = std::string{face->family_name}; + if (familyName.empty()) + CLog::LogF(LOGERROR, "Family name missing in the font"); } } else diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/Observer.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/Observer.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/Observer.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/Observer.h 2013-05-12 08:41:54.000000000 +0000 @@ -48,7 +48,7 @@ public: Observable() = default; virtual ~Observable() = default; - virtual Observable &operator=(const Observable &observable); + Observable& operator=(const Observable& observable); /*! * @brief Register an observer. diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/StreamUtils.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/StreamUtils.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/utils/StreamUtils.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/utils/StreamUtils.h 2013-05-12 08:41:54.000000000 +0000 @@ -8,6 +8,7 @@ #pragma once +#include #include static constexpr int MP4_BOX_HEADER_SIZE = 8; diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/VideoUtils.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/VideoUtils.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/VideoUtils.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/VideoUtils.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -185,6 +185,20 @@ items.Sort(sortDesc); } + if (items.GetContent().empty() && !items.IsVideoDb() && !items.IsVirtualDirectoryRoot() && + !items.IsSourcesPath() && !items.IsLibraryFolder()) + { + CVideoDatabase db; + if (db.Open()) + { + std::string content = db.GetContentForPath(items.GetPath()); + if (content.empty() && !items.IsPlugin()) + content = "files"; + + items.SetContent(content); + } + } + if (m_resume) { // put last played item at the begin of the playlist; add start offsets for videos @@ -226,6 +240,7 @@ const bool unwatchedOnly = watchedMode == WatchedModeUnwatched; const bool watchedOnly = watchedMode == WatchedModeWatched; + bool fetchedPlayCounts = false; for (const auto& i : items) { if (i->m_bIsFolder) @@ -235,11 +250,25 @@ if (StringUtils::EndsWithNoCase(path, "sample")) // skip sample folders continue; } - else if (i->HasVideoInfoTag() && - ((unwatchedOnly && i->GetVideoInfoTag()->GetPlayCount() > 0) || - (watchedOnly && i->GetVideoInfoTag()->GetPlayCount() <= 0))) - continue; - + else + { + if (!fetchedPlayCounts && + (!i->HasVideoInfoTag() || !i->GetVideoInfoTag()->IsPlayCountSet())) + { + CVideoDatabase db; + if (db.Open()) + { + fetchedPlayCounts = true; + db.GetPlayCounts(items.GetPath(), items); + } + } + if (i->HasVideoInfoTag() && i->GetVideoInfoTag()->IsPlayCountSet()) + { + const int playCount = i->GetVideoInfoTag()->GetPlayCount(); + if ((unwatchedOnly && playCount > 0) || (watchedOnly && playCount <= 0)) + continue; + } + } GetItemsForPlaylist(i); } } diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoBase.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoBase.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoBase.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoBase.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -26,6 +26,7 @@ #include "dialogs/GUIDialogSmartPlaylistEditor.h" #include "dialogs/GUIDialogYesNo.h" #include "filesystem/Directory.h" +#include "filesystem/MultiPathDirectory.h" #include "filesystem/StackDirectory.h" #include "filesystem/VideoDatabaseDirectory.h" #include "guilib/GUIComponent.h" @@ -635,6 +636,110 @@ CGUIMediaWindow::OnClick(iItem, player); } +void CGUIWindowVideoBase::LoadVideoInfo(CFileItemList& items, + CVideoDatabase& database, + bool allowReplaceLabels) +{ + //! @todo this could possibly be threaded as per the music info loading, + //! we could also cache the info + if (!items.GetContent().empty() && !items.IsPlugin()) + return; // don't load for listings that have content set and weren't created from plugins + + std::string content = items.GetContent(); + // determine content only if it isn't set + if (content.empty()) + { + content = database.GetContentForPath(items.GetPath()); + items.SetContent((content.empty() && !items.IsPlugin()) ? "files" : content); + } + + /* + If we have a matching item in the library, so we can assign the metadata to it. In addition, we can choose + * whether the item is stacked down (eg in the case of folders representing a single item) + * whether or not we assign the library's labels to the item, or leave the item as is. + + As certain users (read: certain developers) don't want either of these to occur, we compromise by stacking + items down only if stacking is available and enabled. + + Similarly, we assign the "clean" library labels to the item only if the "Replace filenames with library titles" + setting is enabled. + */ + const std::shared_ptr settings = CServiceBroker::GetSettingsComponent()->GetSettings(); + const bool stackItems = + items.GetProperty("isstacked").asBoolean() || + (StackingAvailable(items) && settings->GetBool(CSettings::SETTING_MYVIDEOS_STACKVIDEOS)); + const bool replaceLabels = + allowReplaceLabels && settings->GetBool(CSettings::SETTING_MYVIDEOS_REPLACELABELS); + + CFileItemList dbItems; + /* NOTE: In the future when GetItemsForPath returns all items regardless of whether they're "in the library" + we won't need the fetchedPlayCounts code, and can "simply" do this directly on absence of content. */ + bool fetchedPlayCounts = false; + if (!content.empty()) + { + database.GetItemsForPath(content, items.GetPath(), dbItems); + dbItems.SetFastLookup(true); + } + + for (int i = 0; i < items.Size(); i++) + { + CFileItemPtr pItem = items[i]; + CFileItemPtr match; + + if (pItem->m_bIsFolder && !pItem->IsParentFolder()) + { + // we need this for enabling the right context menu entries, like mark watched / unwatched + pItem->SetProperty("IsVideoFolder", true); + } + + if (!content + .empty()) /* optical media will be stacked down, so it's path won't match the base path */ + { + std::string pathToMatch = + pItem->IsOpticalMediaFile() ? pItem->GetLocalMetadataPath() : pItem->GetPath(); + if (URIUtils::IsMultiPath(pathToMatch)) + pathToMatch = CMultiPathDirectory::GetFirstPath(pathToMatch); + match = dbItems.Get(pathToMatch); + } + if (match) + { + pItem->UpdateInfo(*match, replaceLabels); + + if (stackItems) + { + if (match->m_bIsFolder) + pItem->SetPath(match->GetVideoInfoTag()->m_strPath); + else + pItem->SetPath(match->GetVideoInfoTag()->m_strFileNameAndPath); + // if we switch from a file to a folder item it means we really shouldn't be sorting files and + // folders separately + if (pItem->m_bIsFolder != match->m_bIsFolder) + { + items.SetSortIgnoreFolders(true); + pItem->m_bIsFolder = match->m_bIsFolder; + } + } + } + else + { + /* NOTE: Currently we GetPlayCounts on our items regardless of whether content is set + as if content is set, GetItemsForPaths doesn't return anything not in the content tables. + This code can be removed once the content tables are always filled */ + if (!pItem->m_bIsFolder && !fetchedPlayCounts) + { + database.GetPlayCounts(items.GetPath(), items); + fetchedPlayCounts = true; + } + + // set the watched overlay + if (pItem->IsVideo()) + pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, + pItem->HasVideoInfoTag() && + pItem->GetVideoInfoTag()->GetPlayCount() > 0); + } + } +} + std::string CGUIWindowVideoBase::GetResumeString(const CFileItem &item) { const VIDEO_UTILS::ResumeInformation resumeInfo = VIDEO_UTILS::GetItemResumeInformation(item); diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoBase.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoBase.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoBase.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoBase.h 2013-05-12 08:41:54.000000000 +0000 @@ -71,6 +71,16 @@ */ static std::string GetResumeString(const CFileItem &item); + /*! \brief Load video information from the database for these items (public static version) + Useful for grabbing information for file listings, from watched status to full metadata + \param items the items to load information for. + \param database open database object to retrieve the data from + \param allowReplaceLabels allow label replacement if according GUI setting is enabled + */ + static void LoadVideoInfo(CFileItemList& items, + CVideoDatabase& database, + bool allowReplaceLabels = true); + protected: void OnScan(const std::string& strPath, bool scanAll = false); bool Update(const std::string &strDirectory, bool updateFilterPath = true) override; diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoNav.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoNav.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoNav.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoNav.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -16,7 +16,6 @@ #include "dialogs/GUIDialogMediaSource.h" #include "dialogs/GUIDialogYesNo.h" #include "filesystem/Directory.h" -#include "filesystem/MultiPathDirectory.h" #include "filesystem/VideoDatabaseDirectory.h" #include "filesystem/VideoDatabaseFile.h" #include "guilib/GUIComponent.h" @@ -490,7 +489,7 @@ if (items.GetLabel().empty() && m_rootDir.IsSource(items.GetPath(), CMediaSourceSettings::GetInstance().GetSources("video"), &label)) items.SetLabel(label); if (!items.IsSourcesPath() && !items.IsLibraryFolder()) - LoadVideoInfo(items); + LoadVideoInfo(items, m_database); } CVideoDbUrl videoUrl; @@ -507,106 +506,6 @@ return bResult; } -void CGUIWindowVideoNav::LoadVideoInfo(CFileItemList &items) -{ - LoadVideoInfo(items, m_database); -} - -void CGUIWindowVideoNav::LoadVideoInfo(CFileItemList &items, CVideoDatabase &database, bool allowReplaceLabels) -{ - //! @todo this could possibly be threaded as per the music info loading, - //! we could also cache the info - if (!items.GetContent().empty() && !items.IsPlugin()) - return; // don't load for listings that have content set and weren't created from plugins - - std::string content = items.GetContent(); - // determine content only if it isn't set - if (content.empty()) - { - content = database.GetContentForPath(items.GetPath()); - items.SetContent((content.empty() && !items.IsPlugin()) ? "files" : content); - } - - /* - If we have a matching item in the library, so we can assign the metadata to it. In addition, we can choose - * whether the item is stacked down (eg in the case of folders representing a single item) - * whether or not we assign the library's labels to the item, or leave the item as is. - - As certain users (read: certain developers) don't want either of these to occur, we compromise by stacking - items down only if stacking is available and enabled. - - Similarly, we assign the "clean" library labels to the item only if the "Replace filenames with library titles" - setting is enabled. - */ - const std::shared_ptr settings = CServiceBroker::GetSettingsComponent()->GetSettings(); - const bool stackItems = items.GetProperty("isstacked").asBoolean() || (StackingAvailable(items) && settings->GetBool(CSettings::SETTING_MYVIDEOS_STACKVIDEOS)); - const bool replaceLabels = allowReplaceLabels && settings->GetBool(CSettings::SETTING_MYVIDEOS_REPLACELABELS); - - CFileItemList dbItems; - /* NOTE: In the future when GetItemsForPath returns all items regardless of whether they're "in the library" - we won't need the fetchedPlayCounts code, and can "simply" do this directly on absence of content. */ - bool fetchedPlayCounts = false; - if (!content.empty()) - { - database.GetItemsForPath(content, items.GetPath(), dbItems); - dbItems.SetFastLookup(true); - } - - for (int i = 0; i < items.Size(); i++) - { - CFileItemPtr pItem = items[i]; - CFileItemPtr match; - - if (pItem->m_bIsFolder && !pItem->IsParentFolder()) - { - // we need this for enabling the right context menu entries, like mark watched / unwatched - pItem->SetProperty("IsVideoFolder", true); - } - - if (!content.empty()) /* optical media will be stacked down, so it's path won't match the base path */ - { - std::string pathToMatch = pItem->IsOpticalMediaFile() ? pItem->GetLocalMetadataPath() : pItem->GetPath(); - if (URIUtils::IsMultiPath(pathToMatch)) - pathToMatch = CMultiPathDirectory::GetFirstPath(pathToMatch); - match = dbItems.Get(pathToMatch); - } - if (match) - { - pItem->UpdateInfo(*match, replaceLabels); - - if (stackItems) - { - if (match->m_bIsFolder) - pItem->SetPath(match->GetVideoInfoTag()->m_strPath); - else - pItem->SetPath(match->GetVideoInfoTag()->m_strFileNameAndPath); - // if we switch from a file to a folder item it means we really shouldn't be sorting files and - // folders separately - if (pItem->m_bIsFolder != match->m_bIsFolder) - { - items.SetSortIgnoreFolders(true); - pItem->m_bIsFolder = match->m_bIsFolder; - } - } - } - else - { - /* NOTE: Currently we GetPlayCounts on our items regardless of whether content is set - as if content is set, GetItemsForPaths doesn't return anything not in the content tables. - This code can be removed once the content tables are always filled */ - if (!pItem->m_bIsFolder && !fetchedPlayCounts) - { - database.GetPlayCounts(items.GetPath(), items); - fetchedPlayCounts = true; - } - - // set the watched overlay - if (pItem->IsVideo()) - pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, pItem->HasVideoInfoTag() && pItem->GetVideoInfoTag()->GetPlayCount() > 0); - } - } -} - void CGUIWindowVideoNav::UpdateButtons() { CGUIWindowVideoBase::UpdateButtons(); diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoNav.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoNav.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoNav.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoNav.h 2013-05-12 08:41:54.000000000 +0000 @@ -39,21 +39,7 @@ void OnItemInfo(const CFileItem& fileItem, ADDON::ScraperPtr &info) override; - /*! \brief Load video information from the database for these items (public static version) - Useful for grabbing information for file listings, from watched status to full metadata - \param items the items to load information for. - \param database open database object to retrieve the data from - \param allowReplaceLabels allow label replacement if according GUI setting is enabled - */ - static void LoadVideoInfo(CFileItemList &items, CVideoDatabase &database, bool allowReplaceLabels = true); - protected: - /*! \brief Load video information from the database for these items - Useful for grabbing information for file listings, from watched status to full metadata - \param items the items to load information for. - */ - void LoadVideoInfo(CFileItemList &items); - bool ApplyWatchedFilter(CFileItemList &items); bool GetFilteredItems(const std::string &filter, CFileItemList &items) override; diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoPlaylist.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoPlaylist.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoPlaylist.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoPlaylist.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -25,6 +25,7 @@ #include "input/actions/ActionIDs.h" #include "playlists/PlayListM3U.h" #include "settings/MediaSettings.h" +#include "settings/MediaSourceSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "utils/URIUtils.h" @@ -53,6 +54,25 @@ CGUIWindowVideoPlaylist::~CGUIWindowVideoPlaylist() = default; +void CGUIWindowVideoPlaylist::OnPrepareFileItems(CFileItemList& items) +{ + CGUIWindowVideoBase::OnPrepareFileItems(items); + + if (items.IsEmpty()) + return; + + if (!items.IsVideoDb() && !items.IsVirtualDirectoryRoot()) + { // load info from the database + std::string label; + if (items.GetLabel().empty() && + m_rootDir.IsSource(items.GetPath(), CMediaSourceSettings::GetInstance().GetSources("video"), + &label)) + items.SetLabel(label); + if (!items.IsSourcesPath() && !items.IsLibraryFolder()) + LoadVideoInfo(items, m_database); + } +} + bool CGUIWindowVideoPlaylist::OnMessage(CGUIMessage& message) { switch ( message.GetMessage() ) diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoPlaylist.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoPlaylist.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/video/windows/GUIWindowVideoPlaylist.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/video/windows/GUIWindowVideoPlaylist.h 2013-05-12 08:41:54.000000000 +0000 @@ -16,6 +16,7 @@ CGUIWindowVideoPlaylist(void); ~CGUIWindowVideoPlaylist(void) override; + void OnPrepareFileItems(CFileItemList& items) override; bool OnMessage(CGUIMessage& message) override; bool OnAction(const CAction &action) override; bool OnBack(int actionID) override; diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/windowing/Resolution.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/windowing/Resolution.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/windowing/Resolution.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/windowing/Resolution.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -71,7 +71,7 @@ RESOLUTION CResolutionUtils::ChooseBestResolution(float fps, int width, int height, bool is3D) { RESOLUTION res = CServiceBroker::GetWinSystem()->GetGfxContext().GetVideoResolution(); - float weight; + float weight = 0.0f; if (!FindResolutionFromOverride(fps, width, is3D, res, weight, false)) //find a refreshrate from overrides { diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/windowing/windows/WinSystemWin32.cpp kodi-20.2+git20230630.0528-5f418d0b13/xbmc/windowing/windows/WinSystemWin32.cpp --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/windowing/windows/WinSystemWin32.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/windowing/windows/WinSystemWin32.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -180,8 +180,9 @@ const RECT vsRect = GetVirtualScreenRect(); // we check that window is inside of virtual screen rect (sum of all monitors) - if (top != 0 && left != 0 && top > vsRect.top && top + m_nHeight < vsRect.bottom && - left > vsRect.left && left + m_nWidth < vsRect.right) + // top 0 left 0 is a special position that centers the window on the screen + if ((top != 0 || left != 0) && top >= vsRect.top && top + m_nHeight <= vsRect.bottom && + left >= vsRect.left && left + m_nWidth <= vsRect.right) { // restore previous window position m_nLeft = left; @@ -200,8 +201,8 @@ int maxClientWidth = (rcWorkArea.right - rcNcArea.right) - (rcWorkArea.left - rcNcArea.left); int maxClientHeight = (rcWorkArea.bottom - rcNcArea.bottom) - (rcWorkArea.top - rcNcArea.top); - m_nWidth = std::min(m_nWidth, maxClientWidth); - m_nHeight = std::min(m_nHeight, maxClientHeight); + m_nWidth = std::min(m_nWidth, maxClientWidth); + m_nHeight = std::min(m_nHeight, maxClientHeight); CWinSystemBase::SetWindowResolution(m_nWidth, m_nHeight); // center window on desktop @@ -405,8 +406,9 @@ const RECT vsRect = GetVirtualScreenRect(); // we check that window is inside of virtual screen rect (sum of all monitors) - if (top != 0 && left != 0 && top > vsRect.top && top + m_nHeight < vsRect.bottom && - left > vsRect.left && left + m_nWidth < vsRect.right) + // top 0 left 0 is a special position that centers the window on the screen + if ((top != 0 || left != 0) && top >= vsRect.top && top + m_nHeight <= vsRect.bottom && + left >= vsRect.left && left + m_nWidth <= vsRect.right) { // restore previous window position m_nTop = top; @@ -427,8 +429,8 @@ int maxClientHeight = (rcWorkArea.bottom - rcNcArea.bottom) - (rcWorkArea.top - rcNcArea.top); - m_nWidth = std::min(m_nWidth, maxClientWidth); - m_nHeight = std::min(m_nHeight, maxClientHeight); + m_nWidth = std::min(m_nWidth, maxClientWidth); + m_nHeight = std::min(m_nHeight, maxClientHeight); CWinSystemBase::SetWindowResolution(m_nWidth, m_nHeight); // center window on desktop diff -Nru kodi-20.1+git20230312.0705-289ec664e3/xbmc/windowing/X11/GLContextEGL.h kodi-20.2+git20230630.0528-5f418d0b13/xbmc/windowing/X11/GLContextEGL.h --- kodi-20.1+git20230312.0705-289ec664e3/xbmc/windowing/X11/GLContextEGL.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.2+git20230630.0528-5f418d0b13/xbmc/windowing/X11/GLContextEGL.h 2013-05-12 08:41:54.000000000 +0000 @@ -12,6 +12,8 @@ #include "system_egl.h" #include "threads/CriticalSection.h" +#include + #include #ifdef HAVE_EGLEXTANGLE #include