diff options
51 files changed, 1495 insertions, 652 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4df3257a55..8e137c447c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -438,7 +438,7 @@ add_custom_target(gen_skin_pack # Packaging target. This generates system addon, xbt creation, copy files to build tree add_custom_target(generate-packaging ALL - DEPENDS TexturePacker::TexturePacker::Executable export-files gen_skin_pack gen_system_addons ${XBT_FILES}) + DEPENDS TexturePacker::TexturePacker::Executable export-files gen_skin_pack gen_system_addons) # Make sure we build any libs before we look to export-files. # We may need to export some shared libs/data (eg Python) add_dependencies(export-files ${GLOBAL_TARGET_DEPS}) diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index 80e144370b..2bfe7e1992 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -13099,6 +13099,7 @@ msgid "Where no local album cover exists, online art will be used. Where neither msgstr "" #: system/settings/settings.xml +#: xbmc/video/VideoItemArtworkHandler.cpp #: xbmc/music/dialogs/GUIDialogVideoInfo.cpp msgctxt "#20226" msgid "Movie set information folder" @@ -18915,7 +18916,8 @@ msgctxt "#36040" msgid "Detected version of libCEC interface ({0:x}) is lower than the supported version {1:x}." msgstr "" -#: xbmc/video/dialogs/guidialogvideoinfo.cpp +#: xbmc/video/VideoItemArtworkHandler.cpp +#: xbmc/video/dialogs/GUIDialogVideoInfo.cpp #: xbmc/music/dialogs/GUIDialogMusicInfo.cpp msgctxt "#36041" msgid "* Item folder" @@ -23066,8 +23068,9 @@ msgctxt "#39122" msgid "Library Information Sources" msgstr "" -#. Label for section of settings +#. Label for section of settings, label for artwork file browse dialog #: system/settings/settings.xml +#: xbmc/video/dialogs/GUIDialogVideoInfo.cpp msgctxt "#39123" msgid "Artwork" msgstr "" diff --git a/cmake/modules/FindDav1d.cmake b/cmake/modules/FindDav1d.cmake index 9e91a61395..160a53226b 100644 --- a/cmake/modules/FindDav1d.cmake +++ b/cmake/modules/FindDav1d.cmake @@ -3,60 +3,67 @@ # -------- # Finds the dav1d library # -# This will define the following variables:: +# This will define the following target: # -# DAV1D_FOUND - system has dav1d -# DAV1D_INCLUDE_DIRS - the dav1d include directories -# DAV1D_LIBRARIES - the dav1d libraries - -if(ENABLE_INTERNAL_DAV1D) - include(cmake/scripts/common/ModuleHelpers.cmake) - - set(MODULE_LC dav1d) - - SETUP_BUILD_VARS() - - set(DAV1D_VERSION ${${MODULE}_VER}) - - find_program(NINJA_EXECUTABLE ninja REQUIRED) - find_program(MESON_EXECUTABLE meson REQUIRED) - - set(CONFIGURE_COMMAND ${MESON_EXECUTABLE} - --buildtype=release - --default-library=static - --prefix=${DEPENDS_PATH} - --libdir=lib - -Denable_asm=true - -Denable_tools=false - -Denable_examples=false - -Denable_tests=false - ../dav1d) - set(BUILD_COMMAND ${NINJA_EXECUTABLE}) - set(INSTALL_COMMAND ${NINJA_EXECUTABLE} install) - - BUILD_DEP_TARGET() -else() - if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_DAV1D dav1d QUIET) - endif() +# dav1d::dav1d - The dav1d library - find_library(DAV1D_LIBRARY NAMES dav1d libdav1d - PATHS ${PC_DAV1D_LIBDIR}) +if(NOT TARGET dav1d::dav1d) + if(ENABLE_INTERNAL_DAV1D) + include(cmake/scripts/common/ModuleHelpers.cmake) - find_path(DAV1D_INCLUDE_DIR NAMES dav1d/dav1d.h - PATHS ${PC_DAV1D_INCLUDEDIR}) + set(MODULE_LC dav1d) - set(DAV1D_VERSION ${PC_DAV1D_VERSION}) -endif() + SETUP_BUILD_VARS() -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Dav1d - REQUIRED_VARS DAV1D_LIBRARY DAV1D_INCLUDE_DIR - VERSION_VAR DAV1D_VERSION) + set(DAV1D_VERSION ${${MODULE}_VER}) -if(DAV1D_FOUND) - set(DAV1D_INCLUDE_DIRS ${DAV1D_INCLUDE_DIR}) - set(DAV1D_LIBRARIES ${DAV1D_LIBRARY}) -endif() + find_program(NINJA_EXECUTABLE ninja REQUIRED) + find_program(MESON_EXECUTABLE meson REQUIRED) + + set(CONFIGURE_COMMAND ${MESON_EXECUTABLE} + --buildtype=release + --default-library=static + --prefix=${DEPENDS_PATH} + --libdir=lib + -Denable_asm=true + -Denable_tools=false + -Denable_examples=false + -Denable_tests=false + ../dav1d) + set(BUILD_COMMAND ${NINJA_EXECUTABLE}) + set(INSTALL_COMMAND ${NINJA_EXECUTABLE} install) + + BUILD_DEP_TARGET() + else() + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_DAV1D dav1d QUIET) + endif() + + find_library(DAV1D_LIBRARY NAMES dav1d libdav1d + PATHS ${PC_DAV1D_LIBDIR} + NO_CACHE) + + find_path(DAV1D_INCLUDE_DIR NAMES dav1d/dav1d.h + PATHS ${PC_DAV1D_INCLUDEDIR} + NO_CACHE) -mark_as_advanced(DAV1D_INCLUDE_DIR DAV1D_LIBRARY) + set(DAV1D_VERSION ${PC_DAV1D_VERSION}) + endif() + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Dav1d + REQUIRED_VARS DAV1D_LIBRARY DAV1D_INCLUDE_DIR + VERSION_VAR DAV1D_VERSION) + + if(DAV1D_FOUND) + add_library(dav1d::dav1d UNKNOWN IMPORTED) + set_target_properties(dav1d::dav1d PROPERTIES + IMPORTED_LOCATION "${DAV1D_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${DAV1D_INCLUDE_DIR}") + set_property(GLOBAL APPEND PROPERTY INTERNAL_DEPS_PROP dav1d::dav1d) + + if(TARGET dav1d) + add_dependencies(dav1d::dav1d dav1d) + endif() + endif() +endif() diff --git a/cmake/modules/FindDetours.cmake b/cmake/modules/FindDetours.cmake new file mode 100644 index 0000000000..81cc0e9016 --- /dev/null +++ b/cmake/modules/FindDetours.cmake @@ -0,0 +1,37 @@ +#.rst: +# FindDetours +# -------- +# Finds the Detours library +# +# This will define the following target: +# +# windows::Detours - The Detours library + +if(NOT TARGET windows::Detours) + find_path(DETOURS_INCLUDE_DIR NAMES detours.h + NO_CACHE) + + find_library(DETOURS_LIBRARY_RELEASE NAMES detours + NO_CACHE) + find_library(DETOURS_LIBRARY_DEBUG NAMES detoursd + NO_CACHE) + + include(SelectLibraryConfigurations) + select_library_configurations(DETOURS) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Detours + REQUIRED_VARS DETOURS_LIBRARY DETOURS_INCLUDE_DIR) + + if(DETOURS_FOUND) + add_library(windows::Detours UNKNOWN IMPORTED) + set_target_properties(windows::Detours PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${DETOURS_INCLUDE_DIR}" + IMPORTED_LOCATION "${DETOURS_LIBRARY_RELEASE}") + if(DETOURS_LIBRARY_DEBUG) + set_target_properties(windows::Detours PROPERTIES + IMPORTED_LOCATION_DEBUG "${DETOURS_LIBRARY_DEBUG}") + endif() + set_property(GLOBAL APPEND PROPERTY INTERNAL_DEPS_PROP windows::Detours) + endif() +endif() diff --git a/cmake/modules/FindFFMPEG.cmake b/cmake/modules/FindFFMPEG.cmake index 96d9533406..d3291743f7 100644 --- a/cmake/modules/FindFFMPEG.cmake +++ b/cmake/modules/FindFFMPEG.cmake @@ -32,20 +32,21 @@ macro(buildFFMPEG) # Check for dependencies - Must be done before SETUP_BUILD_VARS get_libversion_data("dav1d" "target") find_package(Dav1d ${LIB_DAV1D_VER} MODULE) - if(NOT DAV1D_FOUND) + if(NOT TARGET dav1d::dav1d) message(STATUS "dav1d not found, internal ffmpeg build will be missing AV1 support!") + else() + set(FFMPEG_OPTIONS -DENABLE_DAV1D=ON) endif() set(MODULE_LC ffmpeg) SETUP_BUILD_VARS() - set(FFMPEG_OPTIONS -DENABLE_CCACHE=${ENABLE_CCACHE} - -DCCACHE_PROGRAM=${CCACHE_PROGRAM} - -DENABLE_VAAPI=${ENABLE_VAAPI} - -DENABLE_VDPAU=${ENABLE_VDPAU} - -DENABLE_DAV1D=${DAV1D_FOUND} - -DEXTRA_FLAGS=${FFMPEG_EXTRA_FLAGS}) + list(APPEND FFMPEG_OPTIONS -DENABLE_CCACHE=${ENABLE_CCACHE} + -DCCACHE_PROGRAM=${CCACHE_PROGRAM} + -DENABLE_VAAPI=${ENABLE_VAAPI} + -DENABLE_VDPAU=${ENABLE_VDPAU} + -DEXTRA_FLAGS=${FFMPEG_EXTRA_FLAGS}) if(KODI_DEPENDSBUILD) set(CROSS_ARGS -DDEPENDS_PATH=${DEPENDS_PATH} @@ -87,8 +88,8 @@ macro(buildFFMPEG) BUILD_DEP_TARGET() - if(TARGET dav1d) - add_dependencies(ffmpeg dav1d) + if(TARGET dav1d::dav1d) + add_dependencies(ffmpeg dav1d::dav1d) endif() find_program(BASH_COMMAND bash) @@ -126,37 +127,30 @@ fi") add_library(ffmpeg::libavcodec INTERFACE IMPORTED) set_target_properties(ffmpeg::libavcodec PROPERTIES - FOLDER "FFMPEG - External Projects" INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIR}") add_library(ffmpeg::libavfilter INTERFACE IMPORTED) set_target_properties(ffmpeg::libavfilter PROPERTIES - FOLDER "FFMPEG - External Projects" INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIR}") add_library(ffmpeg::libavformat INTERFACE IMPORTED) set_target_properties(ffmpeg::libavformat PROPERTIES - FOLDER "FFMPEG - External Projects" INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIR}") add_library(ffmpeg::libavutil INTERFACE IMPORTED) set_target_properties(ffmpeg::libavutil PROPERTIES - FOLDER "FFMPEG - External Projects" INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIR}") add_library(ffmpeg::libswscale INTERFACE IMPORTED) set_target_properties(ffmpeg::libswscale PROPERTIES - FOLDER "FFMPEG - External Projects" INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIR}") add_library(ffmpeg::libswresample INTERFACE IMPORTED) set_target_properties(ffmpeg::libswresample PROPERTIES - FOLDER "FFMPEG - External Projects" INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIR}") add_library(ffmpeg::libpostproc INTERFACE IMPORTED) set_target_properties(ffmpeg::libpostproc PROPERTIES - FOLDER "FFMPEG - External Projects" INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIR}") endmacro() @@ -395,7 +389,6 @@ if(FFMPEG_FOUND) if(NOT TARGET ffmpeg::ffmpeg) add_library(ffmpeg::ffmpeg INTERFACE IMPORTED) set_target_properties(ffmpeg::ffmpeg PROPERTIES - FOLDER "External Projects" INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIRS}" INTERFACE_COMPILE_DEFINITIONS "${_ffmpeg_definitions}") endif() diff --git a/cmake/modules/FindFlatBuffers.cmake b/cmake/modules/FindFlatBuffers.cmake index 0553c976ce..924bcd28c1 100644 --- a/cmake/modules/FindFlatBuffers.cmake +++ b/cmake/modules/FindFlatBuffers.cmake @@ -44,8 +44,7 @@ if(NOT TARGET flatbuffers::flatbuffers) add_library(flatbuffers::flatbuffers INTERFACE IMPORTED) set_target_properties(flatbuffers::flatbuffers PROPERTIES - FOLDER "External Projects" - INTERFACE_INCLUDE_DIRECTORIES "${FLATBUFFERS_INCLUDE_DIR}") + INTERFACE_INCLUDE_DIRECTORIES "${FLATBUFFERS_INCLUDE_DIR}") add_dependencies(flatbuffers::flatbuffers flatbuffers::flatc) diff --git a/cmake/modules/FindRapidJSON.cmake b/cmake/modules/FindRapidJSON.cmake index ace4356b0f..44a25b6193 100644 --- a/cmake/modules/FindRapidJSON.cmake +++ b/cmake/modules/FindRapidJSON.cmake @@ -63,7 +63,6 @@ if(NOT TARGET RapidJSON::RapidJSON) if(RAPIDJSON_FOUND) add_library(RapidJSON::RapidJSON INTERFACE IMPORTED) set_target_properties(RapidJSON::RapidJSON PROPERTIES - FOLDER "External Projects" INTERFACE_INCLUDE_DIRECTORIES "${RAPIDJSON_INCLUDE_DIRS}") if(TARGET rapidjson) add_dependencies(RapidJSON::RapidJSON rapidjson) diff --git a/cmake/platform/windows/windows.cmake b/cmake/platform/windows/windows.cmake index b269fe86b5..a5e13a9c5c 100644 --- a/cmake/platform/windows/windows.cmake +++ b/cmake/platform/windows/windows.cmake @@ -1,3 +1,3 @@ -set(PLATFORM_REQUIRED_DEPS D3DX11Effects) +set(PLATFORM_REQUIRED_DEPS D3DX11Effects Detours) set(APP_RENDER_SYSTEM dx11) list(APPEND PLATFORM_DEFINES -DNTDDI_VERSION=NTDDI_WINBLUE -D_WIN32_WINNT=_WIN32_WINNT_WINBLUE) diff --git a/xbmc/guilib/guiinfo/SystemGUIInfo.cpp b/xbmc/guilib/guiinfo/SystemGUIInfo.cpp index 408522ea3e..d6a428fab6 100644 --- a/xbmc/guilib/guiinfo/SystemGUIInfo.cpp +++ b/xbmc/guilib/guiinfo/SystemGUIInfo.cpp @@ -20,10 +20,6 @@ #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" -#include "network/Network.h" -#if defined(TARGET_DARWIN_OSX) -#include "platform/darwin/osx/smc.h" -#endif #include "guilib/guiinfo/GUIInfo.h" #include "guilib/guiinfo/GUIInfoHelper.h" #include "guilib/guiinfo/GUIInfoLabels.h" @@ -38,6 +34,7 @@ #include "storage/discs/IDiscDriveHandler.h" #include "utils/AlarmClock.h" #include "utils/CPUInfo.h" +#include "utils/GpuInfo.h" #include "utils/HDRCapabilities.h" #include "utils/MemUtils.h" #include "utils/StringUtils.h" @@ -50,7 +47,7 @@ using namespace KODI::GUILIB; using namespace KODI::GUILIB::GUIINFO; CSystemGUIInfo::CSystemGUIInfo() -: m_lastSysHeatInfoTime(-SYSTEM_HEAT_UPDATE_INTERVAL) + : m_gpuInfo(CGPUInfo::GetGPUInfo()), m_lastSysHeatInfoTime(-SYSTEM_HEAT_UPDATE_INTERVAL) { } @@ -59,10 +56,11 @@ std::string CSystemGUIInfo::GetSystemHeatInfo(int info) const if (CTimeUtils::GetFrameTime() - m_lastSysHeatInfoTime >= SYSTEM_HEAT_UPDATE_INTERVAL) { m_lastSysHeatInfoTime = CTimeUtils::GetFrameTime(); -#if defined(TARGET_POSIX) CServiceBroker::GetCPUInfo()->GetTemperature(m_cpuTemp); - m_gpuTemp = GetGPUTemperature(); -#endif + if (m_gpuInfo) + { + m_gpuInfo->GetTemperature(m_gpuTemp); + } } std::string text; @@ -89,43 +87,6 @@ std::string CSystemGUIInfo::GetSystemHeatInfo(int info) const return text; } -CTemperature CSystemGUIInfo::GetGPUTemperature() const -{ - int value = 0; - char scale = 0; - -#if defined(TARGET_DARWIN_OSX) - value = SMCGetTemperature(SMC_KEY_GPU_TEMP); - auto temperature = CTemperature::CreateFromCelsius(value); - if (temperature == CTemperature::CreateFromCelsius(0.0)) - { - temperature.SetValid(false); - } - return temperature; -#elif defined(TARGET_WINDOWS_STORE) - return CTemperature::CreateFromCelsius(0); -#else - std::string cmd = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_gpuTempCmd; - int ret = 0; - FILE* p = NULL; - - if (cmd.empty() || !(p = popen(cmd.c_str(), "r"))) - return CTemperature(); - - ret = fscanf(p, "%d %c", &value, &scale); - pclose(p); - - if (ret != 2) - return CTemperature(); -#endif - - if (scale == 'C' || scale == 'c') - return CTemperature::CreateFromCelsius(value); - if (scale == 'F' || scale == 'f') - return CTemperature::CreateFromFahrenheit(value); - return CTemperature(); -} - void CSystemGUIInfo::UpdateFPS() { m_frameCounter++; diff --git a/xbmc/guilib/guiinfo/SystemGUIInfo.h b/xbmc/guilib/guiinfo/SystemGUIInfo.h index ed2ea03b2e..43c4f281c4 100644 --- a/xbmc/guilib/guiinfo/SystemGUIInfo.h +++ b/xbmc/guilib/guiinfo/SystemGUIInfo.h @@ -9,8 +9,11 @@ #pragma once #include "guilib/guiinfo/GUIInfoProvider.h" +#include "utils/GpuInfo.h" #include "utils/Temperature.h" +#include <memory> + namespace KODI { namespace GUILIB @@ -37,7 +40,8 @@ public: private: std::string GetSystemHeatInfo(int info) const; - CTemperature GetGPUTemperature() const; + + std::unique_ptr<CGPUInfo> m_gpuInfo; static const int SYSTEM_HEAT_UPDATE_INTERVAL = 60000; diff --git a/xbmc/platform/android/CMakeLists.txt b/xbmc/platform/android/CMakeLists.txt index 200729cb9a..d4d65d5ad2 100644 --- a/xbmc/platform/android/CMakeLists.txt +++ b/xbmc/platform/android/CMakeLists.txt @@ -1,8 +1,10 @@ set(SOURCES CPUInfoAndroid.cpp + GPUInfoAndroid.cpp MemUtils.cpp PlatformAndroid.cpp) set(HEADERS CPUInfoAndroid.h + GPUInfoAndroid.h PlatformAndroid.h) core_add_library(androidsupport) diff --git a/xbmc/platform/android/GPUInfoAndroid.cpp b/xbmc/platform/android/GPUInfoAndroid.cpp new file mode 100644 index 0000000000..9fa41906f8 --- /dev/null +++ b/xbmc/platform/android/GPUInfoAndroid.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GPUInfoAndroid.h" + +std::unique_ptr<CGPUInfo> CGPUInfo::GetGPUInfo() +{ + return std::make_unique<CGPUInfoAndroid>(); +} + +bool CGPUInfoAndroid::SupportsPlatformTemperature() const +{ + return false; +} + +bool CGPUInfoAndroid::GetGPUPlatformTemperature(CTemperature& temperature) const +{ + return false; +} diff --git a/xbmc/platform/android/GPUInfoAndroid.h b/xbmc/platform/android/GPUInfoAndroid.h new file mode 100644 index 0000000000..0dbd46890c --- /dev/null +++ b/xbmc/platform/android/GPUInfoAndroid.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "platform/posix/GPUInfoPosix.h" + +class CGPUInfoAndroid : public CGPUInfoPosix +{ +public: + CGPUInfoAndroid() = default; + ~CGPUInfoAndroid() = default; + +private: + bool SupportsPlatformTemperature() const override; + bool GetGPUPlatformTemperature(CTemperature& temperature) const override; +}; diff --git a/xbmc/platform/darwin/ios-common/CMakeLists.txt b/xbmc/platform/darwin/ios-common/CMakeLists.txt index 9a95136da4..44476d24f7 100644 --- a/xbmc/platform/darwin/ios-common/CMakeLists.txt +++ b/xbmc/platform/darwin/ios-common/CMakeLists.txt @@ -4,6 +4,7 @@ set(SOURCES AnnounceReceiver.mm DarwinEmbedKeyboardView.mm DarwinEmbedNowPlayingInfoManager.mm DarwinEmbedUtils.mm + GPUInfoDarwinEmbed.cpp NSData+GZIP.m PlatformDarwinEmbedded.cpp) @@ -13,6 +14,7 @@ set(HEADERS AnnounceReceiver.h DarwinEmbedKeyboardView.h DarwinEmbedNowPlayingInfoManager.h DarwinEmbedUtils.h + GPUInfoDarwinEmbed.h NSData+GZIP.h PlatformDarwinEmbedded.h) diff --git a/xbmc/platform/darwin/ios-common/GPUInfoDarwinEmbed.cpp b/xbmc/platform/darwin/ios-common/GPUInfoDarwinEmbed.cpp new file mode 100644 index 0000000000..a9e3b3ac07 --- /dev/null +++ b/xbmc/platform/darwin/ios-common/GPUInfoDarwinEmbed.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GPUInfoDarwinEmbed.h" + +std::unique_ptr<CGPUInfo> CGPUInfo::GetGPUInfo() +{ + return std::make_unique<CGPUInfoDarwinEmbed>(); +} + +bool CGPUInfoDarwinEmbed::SupportsPlatformTemperature() const +{ + return false; +} + +bool CGPUInfoDarwinEmbed::GetGPUPlatformTemperature(CTemperature& temperature) const +{ + return false; +} diff --git a/xbmc/platform/darwin/ios-common/GPUInfoDarwinEmbed.h b/xbmc/platform/darwin/ios-common/GPUInfoDarwinEmbed.h new file mode 100644 index 0000000000..7225e2ff5e --- /dev/null +++ b/xbmc/platform/darwin/ios-common/GPUInfoDarwinEmbed.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "platform/posix/GPUInfoPosix.h" + +class CGPUInfoDarwinEmbed : public CGPUInfoPosix +{ +public: + CGPUInfoDarwinEmbed() = default; + ~CGPUInfoDarwinEmbed() = default; + +private: + bool SupportsPlatformTemperature() const override; + bool GetGPUPlatformTemperature(CTemperature& temperature) const override; +}; diff --git a/xbmc/platform/darwin/osx/CMakeLists.txt b/xbmc/platform/darwin/osx/CMakeLists.txt index 4e3a41de98..01db68f8e8 100644 --- a/xbmc/platform/darwin/osx/CMakeLists.txt +++ b/xbmc/platform/darwin/osx/CMakeLists.txt @@ -1,11 +1,13 @@ set(SOURCES CocoaInterface.mm CPUInfoOsx.cpp + GPUInfoMacOS.cpp HotKeyController.m PlatformDarwinOSX.cpp smc.c) set(HEADERS CocoaInterface.h CPUInfoOsx.h + GPUInfoMacOS.h HotKeyController.h PlatformDarwinOSX.h smc.h) diff --git a/xbmc/platform/darwin/osx/GPUInfoMacOS.cpp b/xbmc/platform/darwin/osx/GPUInfoMacOS.cpp new file mode 100644 index 0000000000..5594d9bbf2 --- /dev/null +++ b/xbmc/platform/darwin/osx/GPUInfoMacOS.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GPUInfoMacOS.h" + +#include "platform/darwin/osx/smc.h" + +std::unique_ptr<CGPUInfo> CGPUInfo::GetGPUInfo() +{ + return std::make_unique<CGPUInfoMacOS>(); +} + +bool CGPUInfoMacOS::SupportsPlatformTemperature() const +{ + return true; +} + +bool CGPUInfoMacOS::GetGPUPlatformTemperature(CTemperature& temperature) const +{ + double temperatureValue = SMCGetTemperature(SMC_KEY_GPU_TEMP); + if (temperatureValue <= 0.0) + { + return false; + } + temperature = CTemperature::CreateFromCelsius(temperatureValue); + return true; +} diff --git a/xbmc/platform/darwin/osx/GPUInfoMacOS.h b/xbmc/platform/darwin/osx/GPUInfoMacOS.h new file mode 100644 index 0000000000..8ceb02d578 --- /dev/null +++ b/xbmc/platform/darwin/osx/GPUInfoMacOS.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "platform/posix/GPUInfoPosix.h" + +class CGPUInfoMacOS : public CGPUInfoPosix +{ +public: + CGPUInfoMacOS() = default; + ~CGPUInfoMacOS() = default; + +private: + bool SupportsPlatformTemperature() const override; + bool GetGPUPlatformTemperature(CTemperature& temperature) const override; +}; diff --git a/xbmc/platform/darwin/osx/network/NetworkMacOS.mm b/xbmc/platform/darwin/osx/network/NetworkMacOS.mm index 649007bc1e..ac63317cf9 100644 --- a/xbmc/platform/darwin/osx/network/NetworkMacOS.mm +++ b/xbmc/platform/darwin/osx/network/NetworkMacOS.mm @@ -6,7 +6,7 @@ * See LICENSES/README.md for more information. */ -#include "NetworkmacOS.h" +#include "NetworkMacOS.h" #include "utils/StringUtils.h" #include "utils/log.h" diff --git a/xbmc/platform/freebsd/CMakeLists.txt b/xbmc/platform/freebsd/CMakeLists.txt index 3506c2ee70..b8818cefc3 100644 --- a/xbmc/platform/freebsd/CMakeLists.txt +++ b/xbmc/platform/freebsd/CMakeLists.txt @@ -1,5 +1,6 @@ set(SOURCES ../linux/AppParamParserLinux.cpp CPUInfoFreebsd.cpp + GPUInfoFreebsd.cpp OptionalsReg.cpp ../linux/OptionalsReg.cpp ../linux/TimeUtils.cpp @@ -8,6 +9,7 @@ set(SOURCES ../linux/AppParamParserLinux.cpp set(HEADERS ../linux/AppParamParserLinux.cpp CPUInfoFreebsd.h + GPUInfoFreebsd.h OptionalsReg.h ../linux/OptionalsReg.h ../linux/TimeUtils.h diff --git a/xbmc/platform/freebsd/GPUInfoFreebsd.cpp b/xbmc/platform/freebsd/GPUInfoFreebsd.cpp new file mode 100644 index 0000000000..030b652d23 --- /dev/null +++ b/xbmc/platform/freebsd/GPUInfoFreebsd.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GPUInfoFreebsd.h" + +std::unique_ptr<CGPUInfo> CGPUInfo::GetGPUInfo() +{ + return std::make_unique<CGPUInfoFreebsd>(); +} + +bool CGPUInfoFreebsd::SupportsPlatformTemperature() const +{ + return false; +} + +bool CGPUInfoFreebsd::GetGPUPlatformTemperature(CTemperature& temperature) const +{ + return false; +} diff --git a/xbmc/platform/freebsd/GPUInfoFreebsd.h b/xbmc/platform/freebsd/GPUInfoFreebsd.h new file mode 100644 index 0000000000..62016ecc40 --- /dev/null +++ b/xbmc/platform/freebsd/GPUInfoFreebsd.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "platform/posix/GPUInfoPosix.h" + +class CGPUInfoFreebsd : public CGPUInfoPosix +{ +public: + CGPUInfoFreebsd() = default; + ~CGPUInfoFreebsd() = default; + +private: + bool SupportsPlatformTemperature() const override; + bool GetGPUPlatformTemperature(CTemperature& temperature) const override; +}; diff --git a/xbmc/platform/linux/CMakeLists.txt b/xbmc/platform/linux/CMakeLists.txt index 0c8bccf8c0..08a696498e 100644 --- a/xbmc/platform/linux/CMakeLists.txt +++ b/xbmc/platform/linux/CMakeLists.txt @@ -1,5 +1,6 @@ set(SOURCES AppParamParserLinux.cpp CPUInfoLinux.cpp + GPUInfoLinux.cpp MemUtils.cpp OptionalsReg.cpp PlatformLinux.cpp @@ -8,6 +9,7 @@ set(SOURCES AppParamParserLinux.cpp set(HEADERS AppParamParserLinux.h CPUInfoLinux.h + GPUInfoLinux.h OptionalsReg.h PlatformLinux.h SysfsPath.h diff --git a/xbmc/platform/linux/GPUInfoLinux.cpp b/xbmc/platform/linux/GPUInfoLinux.cpp new file mode 100644 index 0000000000..dd8585a204 --- /dev/null +++ b/xbmc/platform/linux/GPUInfoLinux.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GPUInfoLinux.h" + +std::unique_ptr<CGPUInfo> CGPUInfo::GetGPUInfo() +{ + return std::make_unique<CGPUInfoLinux>(); +} + +bool CGPUInfoLinux::SupportsPlatformTemperature() const +{ + return false; +} + +bool CGPUInfoLinux::GetGPUPlatformTemperature(CTemperature& temperature) const +{ + return false; +} diff --git a/xbmc/platform/linux/GPUInfoLinux.h b/xbmc/platform/linux/GPUInfoLinux.h new file mode 100644 index 0000000000..152068fa0f --- /dev/null +++ b/xbmc/platform/linux/GPUInfoLinux.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "platform/posix/GPUInfoPosix.h" + +class CGPUInfoLinux : public CGPUInfoPosix +{ +public: + CGPUInfoLinux() = default; + ~CGPUInfoLinux() = default; + +private: + bool SupportsPlatformTemperature() const override; + bool GetGPUPlatformTemperature(CTemperature& temperature) const override; +}; diff --git a/xbmc/platform/posix/CMakeLists.txt b/xbmc/platform/posix/CMakeLists.txt index 2d8d4dbd63..7907159cf9 100644 --- a/xbmc/platform/posix/CMakeLists.txt +++ b/xbmc/platform/posix/CMakeLists.txt @@ -1,6 +1,7 @@ set(SOURCES ConvUtils.cpp CPUInfoPosix.cpp Filesystem.cpp + GPUInfoPosix.cpp MessagePrinter.cpp PlatformPosix.cpp PosixMountProvider.cpp @@ -11,6 +12,7 @@ set(SOURCES ConvUtils.cpp set(HEADERS ConvUtils.h CPUInfoPosix.h + GPUInfoPosix.h PlatformDefs.h PlatformPosix.h PosixMountProvider.h diff --git a/xbmc/platform/posix/GPUInfoPosix.cpp b/xbmc/platform/posix/GPUInfoPosix.cpp new file mode 100644 index 0000000000..1f4a957041 --- /dev/null +++ b/xbmc/platform/posix/GPUInfoPosix.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GPUInfoPosix.h" + +#include <stdio.h> + +bool CGPUInfoPosix::SupportsCustomTemperatureCommand() const +{ + return true; +} + +bool CGPUInfoPosix::GetGPUTemperatureFromCommand(CTemperature& temperature, + const std::string& cmd) const +{ + int value = 0; + char scale = 0; + int ret = 0; + FILE* p = nullptr; + + if (cmd.empty() || !(p = popen(cmd.c_str(), "r"))) + { + return false; + } + + ret = fscanf(p, "%d %c", &value, &scale); + pclose(p); + + if (ret != 2) + { + return false; + } + + if (scale == 'C' || scale == 'c') + { + temperature = CTemperature::CreateFromCelsius(value); + } + else if (scale == 'F' || scale == 'f') + { + temperature = CTemperature::CreateFromFahrenheit(value); + } + else + { + return false; + } + return true; +} diff --git a/xbmc/platform/posix/GPUInfoPosix.h b/xbmc/platform/posix/GPUInfoPosix.h new file mode 100644 index 0000000000..b03914e73f --- /dev/null +++ b/xbmc/platform/posix/GPUInfoPosix.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "utils/GpuInfo.h" + +class CGPUInfoPosix : public CGPUInfo +{ +protected: + CGPUInfoPosix() = default; + virtual ~CGPUInfoPosix() = default; + + virtual bool SupportsCustomTemperatureCommand() const override; + virtual bool GetGPUTemperatureFromCommand(CTemperature& temperature, + const std::string& cmd) const override; +}; diff --git a/xbmc/platform/win10/CMakeLists.txt b/xbmc/platform/win10/CMakeLists.txt index 6ddf3c8df7..19bc19f0e5 100644 --- a/xbmc/platform/win10/CMakeLists.txt +++ b/xbmc/platform/win10/CMakeLists.txt @@ -1,6 +1,7 @@ set(SOURCES CPUInfoWin10.cpp input/RemoteControlXbox.cpp Environment.cpp + GPUInfoWin10.cpp Win10App.cpp MessagePrinter.cpp PlatformWin10.cpp @@ -14,6 +15,7 @@ set(SOURCES CPUInfoWin10.cpp set(HEADERS AsyncHelpers.h CPUInfoWin10.h + GPUInfoWin10.h input/RemoteControlXbox.h Win10App.h PlatformWin10.h diff --git a/xbmc/platform/win10/GPUInfoWin10.cpp b/xbmc/platform/win10/GPUInfoWin10.cpp new file mode 100644 index 0000000000..8c6fb1a661 --- /dev/null +++ b/xbmc/platform/win10/GPUInfoWin10.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GPUInfoWin10.h" + +std::unique_ptr<CGPUInfo> CGPUInfo::GetGPUInfo() +{ + return std::make_unique<CGPUInfoWin10>(); +} + +bool CGPUInfoWin10::SupportsCustomTemperatureCommand() const +{ + return false; +} + +bool CGPUInfoWin10::SupportsPlatformTemperature() const +{ + return false; +} + +bool CGPUInfoWin10::GetGPUPlatformTemperature(CTemperature& temperature) const +{ + return false; +} + +bool CGPUInfoWin10::GetGPUTemperatureFromCommand(CTemperature& temperature, + const std::string& cmd) const +{ + return false; +} diff --git a/xbmc/platform/win10/GPUInfoWin10.h b/xbmc/platform/win10/GPUInfoWin10.h new file mode 100644 index 0000000000..6e7d0329af --- /dev/null +++ b/xbmc/platform/win10/GPUInfoWin10.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "utils/GpuInfo.h" + +class CGPUInfoWin10 : public CGPUInfo +{ +public: + CGPUInfoWin10() = default; + ~CGPUInfoWin10() = default; + +private: + bool SupportsCustomTemperatureCommand() const override; + bool SupportsPlatformTemperature() const override; + bool GetGPUPlatformTemperature(CTemperature& temperature) const override; + bool GetGPUTemperatureFromCommand(CTemperature& temperature, + const std::string& cmd) const override; +}; diff --git a/xbmc/platform/win32/CMakeLists.txt b/xbmc/platform/win32/CMakeLists.txt index 57afab0e41..28faedb9c0 100644 --- a/xbmc/platform/win32/CMakeLists.txt +++ b/xbmc/platform/win32/CMakeLists.txt @@ -1,6 +1,7 @@ set(SOURCES CharsetConverter.cpp CPUInfoWin32.cpp Environment.cpp + GPUInfoWin32.cpp MemUtils.cpp MessagePrinter.cpp dxerr.cpp @@ -15,6 +16,7 @@ set(HEADERS CharsetConverter.h CPUInfoWin32.h dirent.h dxerr.h + GPUInfoWin32.h IMMNotificationClient.h my_ntddcdrm.h my_ntddscsi.h diff --git a/xbmc/platform/win32/GPUInfoWin32.cpp b/xbmc/platform/win32/GPUInfoWin32.cpp new file mode 100644 index 0000000000..bdf0b0f17f --- /dev/null +++ b/xbmc/platform/win32/GPUInfoWin32.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GPUInfoWin32.h" + +std::unique_ptr<CGPUInfo> CGPUInfo::GetGPUInfo() +{ + return std::make_unique<CGPUInfoWin32>(); +} + +bool CGPUInfoWin32::SupportsCustomTemperatureCommand() const +{ + return false; +} + +bool CGPUInfoWin32::SupportsPlatformTemperature() const +{ + return false; +} + +bool CGPUInfoWin32::GetGPUPlatformTemperature(CTemperature& temperature) const +{ + return false; +} + +bool CGPUInfoWin32::GetGPUTemperatureFromCommand(CTemperature& temperature, + const std::string& cmd) const +{ + return false; +} diff --git a/xbmc/platform/win32/GPUInfoWin32.h b/xbmc/platform/win32/GPUInfoWin32.h new file mode 100644 index 0000000000..e23bccb84f --- /dev/null +++ b/xbmc/platform/win32/GPUInfoWin32.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "utils/GpuInfo.h" + +class CGPUInfoWin32 : public CGPUInfo +{ +public: + CGPUInfoWin32() = default; + ~CGPUInfoWin32() = default; + +private: + bool GetGPUPlatformTemperature(CTemperature& temperature) const override; + bool GetGPUTemperatureFromCommand(CTemperature& temperature, + const std::string& cmd) const override; + bool SupportsCustomTemperatureCommand() const override; + bool SupportsPlatformTemperature() const override; +}; diff --git a/xbmc/pvr/recordings/PVRRecordingsPath.cpp b/xbmc/pvr/recordings/PVRRecordingsPath.cpp index 85883ea8fb..29bb7cff22 100644 --- a/xbmc/pvr/recordings/PVRRecordingsPath.cpp +++ b/xbmc/pvr/recordings/PVRRecordingsPath.cpp @@ -46,7 +46,7 @@ CPVRRecordingsPath::CPVRRecordingsPath(const std::string& strPath) strVarPath.append("/"); else { - size_t paramStart = m_path.find(", TV"); + size_t paramStart = strVarPath.find(", TV"); if (paramStart == std::string::npos) m_directoryPath = strVarPath.substr(GetDirectoryPathPosition()); else diff --git a/xbmc/utils/CMakeLists.txt b/xbmc/utils/CMakeLists.txt index c7c053b821..fd9f4ab44f 100644 --- a/xbmc/utils/CMakeLists.txt +++ b/xbmc/utils/CMakeLists.txt @@ -27,6 +27,7 @@ set(SOURCES ActorProtocol.cpp FileOperationJob.cpp FileUtils.cpp FontUtils.cpp + GpuInfo.cpp GroupUtils.cpp HTMLUtil.cpp HttpHeader.cpp @@ -111,6 +112,7 @@ set(HEADERS ActorProtocol.h FontUtils.h Geometry.h GlobalsHandling.h + GpuInfo.h GroupUtils.h HDRCapabilities.h HTMLUtil.h diff --git a/xbmc/utils/GpuInfo.cpp b/xbmc/utils/GpuInfo.cpp new file mode 100644 index 0000000000..9d1db907ba --- /dev/null +++ b/xbmc/utils/GpuInfo.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GpuInfo.h" + +#include "ServiceBroker.h" +#include "settings/AdvancedSettings.h" +#include "settings/SettingsComponent.h" + +bool CGPUInfo::GetTemperature(CTemperature& temperature) const +{ + // user custom cmd takes precedence over platform implementation + if (SupportsCustomTemperatureCommand()) + { + auto cmd = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_gpuTempCmd; + if (!cmd.empty() && GetGPUTemperatureFromCommand(temperature, cmd)) + { + return true; + } + } + + if (SupportsPlatformTemperature() && GetGPUPlatformTemperature(temperature)) + { + return true; + } + + temperature = CTemperature(); + temperature.SetValid(false); + return false; +} diff --git a/xbmc/utils/GpuInfo.h b/xbmc/utils/GpuInfo.h new file mode 100644 index 0000000000..26a71a8d28 --- /dev/null +++ b/xbmc/utils/GpuInfo.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "utils/Temperature.h" + +#include <memory> +#include <string> + +/*! \brief Class to concentrate all methods related to GPU information +* \details This is used by the Info interface to obtain the current GPU temperature +*/ +class CGPUInfo +{ +public: + CGPUInfo() = default; + virtual ~CGPUInfo() = default; + + /*! \brief Getter from the specific platform GPUInfo + \return the platform specific implementation of GPUInfo + */ + static std::unique_ptr<CGPUInfo> GetGPUInfo(); + + /*! \brief Get the temperature of the GPU + \param[in,out] temperature - the temperature to fill with the result + \return true if it was possible to obtain the GPU temperature, false otherwise + */ + bool GetTemperature(CTemperature& temperature) const; + +protected: + /*! \brief Checks if the specific platform implementation supports obtaining the GPU temperature + via the execution of a custom command line command + \note this is false on the base class but may be overridden by the specific platform implementation. + Custom GPU command is defined in advancedsettings. + \return true if the implementation supports obtaining the GPU temperature from a custom command, false otherwise + */ + virtual bool SupportsCustomTemperatureCommand() const { return false; } + + /*! \brief Checks if the specific platform implementation supports obtaining the GPU temperature + from the platform SDK itself + \note this is false on the base class but may be overridden by the specific platform implementation. + \return true if the implementation supports obtaining the GPU temperature from the platform SDK, false otherwise + */ + virtual bool SupportsPlatformTemperature() const { return false; } + + /*! \brief Get the GPU temperature from the platform SDK + \note platform implementations must override this. For this to take effect SupportsPlatformTemperature must be true. + \param[in,out] temperature - the temperature to fill with the result + \return true if obtaining the GPU temperature succeeded, false otherwise + */ + virtual bool GetGPUPlatformTemperature(CTemperature& temperature) const = 0; + + /*! \brief Get the GPU temperature from a user provided command (advanced settings) + \note platform implementations must override this. For this to take effect SupportsCustomTemperatureCommand must be true. + \param[in,out] temperature - the temperature to fill with the result + \return true if obtaining the GPU temperature succeeded, false otherwise + */ + virtual bool GetGPUTemperatureFromCommand(CTemperature& temperature, + const std::string& cmd) const = 0; +}; diff --git a/xbmc/utils/test/CMakeLists.txt b/xbmc/utils/test/CMakeLists.txt index 5cff468669..0ce2a6fafe 100644 --- a/xbmc/utils/test/CMakeLists.txt +++ b/xbmc/utils/test/CMakeLists.txt @@ -14,6 +14,7 @@ set(SOURCES TestAlarmClock.cpp TestFileOperationJob.cpp TestFileUtils.cpp TestGlobalsHandling.cpp + TestGPUInfo.cpp TestHTMLUtil.cpp TestHttpHeader.cpp TestHttpParser.cpp diff --git a/xbmc/utils/test/TestGPUInfo.cpp b/xbmc/utils/test/TestGPUInfo.cpp new file mode 100644 index 0000000000..331a62c3bd --- /dev/null +++ b/xbmc/utils/test/TestGPUInfo.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "ServiceBroker.h" +#include "settings/AdvancedSettings.h" +#include "settings/SettingsComponent.h" +#include "utils/GpuInfo.h" + +#include <memory> + +#include <gtest/gtest.h> + +class TestGPUInfo : public ::testing::Test +{ +protected: + TestGPUInfo() = default; +}; + +#if defined(TARGET_WINDOWS) +TEST_F(TestGPUInfo, DISABLED_GetTemperatureFromCmd) +#else +TEST_F(TestGPUInfo, GetTemperature) +#endif +{ + CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_gpuTempCmd = "echo '50 c'"; + std::unique_ptr<CGPUInfo> gpuInfo = CGPUInfo::GetGPUInfo(); + EXPECT_NE(gpuInfo, nullptr); + CTemperature t; + bool success = gpuInfo->GetTemperature(t); + EXPECT_TRUE(success); + EXPECT_TRUE(t.IsValid()); + EXPECT_EQ(t.ToCelsius(), 50); +} diff --git a/xbmc/video/CMakeLists.txt b/xbmc/video/CMakeLists.txt index 1deed57cd0..b5068599b7 100644 --- a/xbmc/video/CMakeLists.txt +++ b/xbmc/video/CMakeLists.txt @@ -3,6 +3,7 @@ set(SOURCES Bookmark.cpp GUIViewStateVideo.cpp PlayerController.cpp Teletext.cpp + VideoItemArtworkHandler.cpp VideoDatabase.cpp VideoDbUrl.cpp VideoEmbeddedImageFileLoader.cpp @@ -22,6 +23,7 @@ set(HEADERS Bookmark.h PlayerController.h Teletext.h TeletextDefines.h + VideoItemArtworkHandler.h VideoDatabase.h VideoDbUrl.h VideoEmbeddedImageFileLoader.h diff --git a/xbmc/video/VideoItemArtworkHandler.cpp b/xbmc/video/VideoItemArtworkHandler.cpp new file mode 100644 index 0000000000..0401c832b3 --- /dev/null +++ b/xbmc/video/VideoItemArtworkHandler.cpp @@ -0,0 +1,554 @@ +/* + * Copyright (C) 2005-2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "VideoItemArtworkHandler.h" + +#include "FileItem.h" +#include "MediaSource.h" +#include "ServiceBroker.h" +#include "TextureDatabase.h" +#include "filesystem/Directory.h" +#include "guilib/LocalizeStrings.h" +#include "music/MusicDatabase.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "utils/FileExtensionProvider.h" +#include "utils/FileUtils.h" +#include "utils/URIUtils.h" +#include "utils/Variant.h" +#include "utils/log.h" +#include "video/VideoDatabase.h" +#include "video/VideoInfoScanner.h" +#include "video/VideoInfoTag.h" +#include "video/VideoThumbLoader.h" +#include "video/tags/VideoTagExtractionHelper.h" + +using namespace VIDEO; +using namespace XFILE; + +namespace +{ +//------------------------------------------------------------------------------------------------- +// CVideoItemArtworkHandler (Generic handler) +//------------------------------------------------------------------------------------------------- + +class CVideoItemArtworkHandler : public IVideoItemArtworkHandler +{ +public: + explicit CVideoItemArtworkHandler(const std::shared_ptr<CFileItem>& item, + const std::string& artType) + : m_item(item), m_artType(artType) + { + } + + std::string GetCurrentArt() const override; + std::string GetEmbeddedArt() const override; + std::vector<std::string> GetRemoteArt() const override; + std::string GetLocalArt() const override; + + std::string GetDefaultIcon() const override; + + void AddItemPathToFileBrowserSources(std::vector<CMediaSource>& sources) override; + + void PersistArt(const std::string& art) override; + +protected: + void AddItemPathStringToFileBrowserSources(std::vector<CMediaSource>& sources, + const std::string& itemDir, + const std::string& label); + + const std::shared_ptr<CFileItem> m_item; + const std::string m_artType; +}; + +std::string CVideoItemArtworkHandler::GetCurrentArt() const +{ + if (m_artType.empty()) + { + CLog::LogF(LOGERROR, "Art type not set!"); + return {}; + } + + std::string currentArt; + if (m_item->HasArt(m_artType)) + currentArt = m_item->GetArt(m_artType); + else if (m_item->HasArt("thumb") && (m_artType == "poster" || m_artType == "banner")) + currentArt = m_item->GetArt("thumb"); + + return currentArt; +} + +std::string CVideoItemArtworkHandler::GetEmbeddedArt() const +{ + if (TAGS::CVideoTagExtractionHelper::IsExtractionSupportedFor(*m_item)) + return TAGS::CVideoTagExtractionHelper::ExtractEmbeddedArtFor(*m_item, m_artType); + + return {}; +} + +std::vector<std::string> CVideoItemArtworkHandler::GetRemoteArt() const +{ + std::vector<std::string> remoteArt; + CVideoInfoTag tag(*m_item->GetVideoInfoTag()); + tag.m_strPictureURL.Parse(); + tag.m_strPictureURL.GetThumbUrls(remoteArt, m_artType); + return remoteArt; +} + +std::string CVideoItemArtworkHandler::GetLocalArt() const +{ + return CVideoThumbLoader::GetLocalArt(*m_item, m_artType); +} + +std::string CVideoItemArtworkHandler::GetDefaultIcon() const +{ + return m_item->m_bIsFolder ? "DefaultFolder.png" : "DefaultPicture.png"; +} + +void CVideoItemArtworkHandler::AddItemPathToFileBrowserSources(std::vector<CMediaSource>& sources) +{ + std::string itemDir = m_item->GetVideoInfoTag()->m_basePath; + //season + if (itemDir.empty()) + itemDir = m_item->GetVideoInfoTag()->GetPath(); + + const CFileItem itemTmp(itemDir, false); + if (itemTmp.IsVideo()) + itemDir = URIUtils::GetParentPath(itemDir); + + AddItemPathStringToFileBrowserSources(sources, itemDir, + g_localizeStrings.Get(36041) /* * Item folder */); +} + +void CVideoItemArtworkHandler::PersistArt(const std::string& art) +{ + CVideoDatabase videodb; + if (!videodb.Open()) + { + CLog::LogF(LOGERROR, "Cannot open video database!"); + return; + } + + videodb.SetArtForItem(m_item->GetVideoInfoTag()->m_iDbId, m_item->GetVideoInfoTag()->m_type, + m_artType, art); +} + +void CVideoItemArtworkHandler::AddItemPathStringToFileBrowserSources( + std::vector<CMediaSource>& sources, const std::string& itemDir, const std::string& label) +{ + if (!itemDir.empty() && CDirectory::Exists(itemDir)) + { + CMediaSource itemSource; + itemSource.strName = label; + itemSource.strPath = itemDir; + sources.emplace_back(itemSource); + } +} + +//------------------------------------------------------------------------------------------------- +// CVideoItemArtworkArtistHandler (Artist handler) +//------------------------------------------------------------------------------------------------- + +class CVideoItemArtworkArtistHandler : public CVideoItemArtworkHandler +{ +public: + explicit CVideoItemArtworkArtistHandler(const std::shared_ptr<CFileItem>& item, + const std::string& artType) + : CVideoItemArtworkHandler(item, artType) + { + } + + std::string GetCurrentArt() const override; + std::vector<std::string> GetRemoteArt() const override; + std::string GetLocalArt() const override; + + std::string GetDefaultIcon() const override { return "DefaultArtist.png"; } + + void PersistArt(const std::string& art) override; +}; + +std::string CVideoItemArtworkArtistHandler::GetCurrentArt() const +{ + CMusicDatabase musicdb; + if (!musicdb.Open()) + { + CLog::LogF(LOGERROR, "Cannot open music database!"); + return {}; + } + + std::string currentArt; + const int idArtist = musicdb.GetArtistByName(m_item->GetLabel()); + if (idArtist >= 0) + currentArt = musicdb.GetArtForItem(idArtist, MediaTypeArtist, "thumb"); + + if (currentArt.empty()) + { + CVideoDatabase videodb; + if (!videodb.Open()) + { + CLog::LogF(LOGERROR, "Cannot open video database!"); + return {}; + } + + currentArt = videodb.GetArtForItem(m_item->GetVideoInfoTag()->m_iDbId, + m_item->GetVideoInfoTag()->m_type, "thumb"); + } + return currentArt; +} + +std::vector<std::string> CVideoItemArtworkArtistHandler::GetRemoteArt() const +{ + return {}; +} + +std::string CVideoItemArtworkArtistHandler::GetLocalArt() const +{ + CMusicDatabase musicdb; + if (!musicdb.Open()) + { + CLog::LogF(LOGERROR, "Cannot open music database!"); + return {}; + } + + std::string localArt; + const int idArtist = musicdb.GetArtistByName(m_item->GetLabel()); + if (idArtist >= 0) + { + // Get artist paths - possible locations for thumb - while music db open + CArtist artist; + musicdb.GetArtist(idArtist, artist); + std::string artistPath; + musicdb.GetArtistPath(artist, artistPath); // Artist path in artist info folder + + std::string thumb; + bool existsThumb = false; + + // First look for artist thumb in the primary location + if (!artistPath.empty()) + { + thumb = URIUtils::AddFileToFolder(artistPath, "folder.jpg"); + existsThumb = CFileUtils::Exists(thumb); + } + // If not there fall back local to music files (historic location for those album artists with a unique folder) + if (!existsThumb) + { + std::string artistOldPath; + musicdb.GetOldArtistPath(idArtist, artistOldPath); // Old artist path, local to music files + if (!artistOldPath.empty()) + { + thumb = URIUtils::AddFileToFolder(artistOldPath, "folder.jpg"); + existsThumb = CFileUtils::Exists(thumb); + } + } + + if (existsThumb) + localArt = thumb; + } + return localArt; +} + +void CVideoItemArtworkArtistHandler::PersistArt(const std::string& art) +{ + CMusicDatabase musicdb; + if (!musicdb.Open()) + { + CLog::LogF(LOGERROR, "Cannot open music database!"); + return; + } + + const int idArtist = musicdb.GetArtistByName(m_item->GetLabel()); + if (idArtist >= 0) + musicdb.SetArtForItem(idArtist, MediaTypeArtist, m_artType, art); +} + +//------------------------------------------------------------------------------------------------- +// CVideoItemArtworkActorHandler (Actor handler) +//------------------------------------------------------------------------------------------------- + +class CVideoItemArtworkActorHandler : public CVideoItemArtworkHandler +{ +public: + explicit CVideoItemArtworkActorHandler(const std::shared_ptr<CFileItem>& item, + const std::string& artType) + : CVideoItemArtworkHandler(item, artType) + { + } + + std::string GetCurrentArt() const override; + std::string GetLocalArt() const override; + + std::string GetDefaultIcon() const override { return "DefaultActor.png"; } +}; + +std::string CVideoItemArtworkActorHandler::GetCurrentArt() const +{ + CVideoDatabase videodb; + if (!videodb.Open()) + { + CLog::LogF(LOGERROR, "Cannot open video database!"); + return {}; + } + + return videodb.GetArtForItem(m_item->GetVideoInfoTag()->m_iDbId, + m_item->GetVideoInfoTag()->m_type, "thumb"); +} + +std::string CVideoItemArtworkActorHandler::GetLocalArt() const +{ + std::string localArt; + std::string picturePath; + const std::string thumb = URIUtils::AddFileToFolder(picturePath, "folder.jpg"); + if (CFileUtils::Exists(thumb)) + localArt = thumb; + + return localArt; +} + +//------------------------------------------------------------------------------------------------- +// CVideoItemArtworkSeasonHandler (Season handler) +//------------------------------------------------------------------------------------------------- + +class CVideoItemArtworkSeasonHandler : public CVideoItemArtworkHandler +{ +public: + explicit CVideoItemArtworkSeasonHandler(const std::shared_ptr<CFileItem>& item, + const std::string& artType) + : CVideoItemArtworkHandler(item, artType) + { + } + + std::vector<std::string> GetRemoteArt() const override; +}; + +std::vector<std::string> CVideoItemArtworkSeasonHandler::GetRemoteArt() const +{ + CVideoDatabase videodb; + if (!videodb.Open()) + { + CLog::LogF(LOGERROR, "Cannot open video database!"); + return {}; + } + + std::vector<std::string> remoteArt; + CVideoInfoTag tag; + videodb.GetTvShowInfo("", tag, m_item->GetVideoInfoTag()->m_iIdShow); + tag.m_strPictureURL.Parse(); + tag.m_strPictureURL.GetThumbUrls(remoteArt, m_artType, m_item->GetVideoInfoTag()->m_iSeason); + return remoteArt; +} + +//------------------------------------------------------------------------------------------------- +// CVideoItemArtworkMovieSetHandler (Movie set handler) +//------------------------------------------------------------------------------------------------- + +class CVideoItemArtworkMovieSetHandler : public CVideoItemArtworkHandler +{ +public: + explicit CVideoItemArtworkMovieSetHandler(const std::shared_ptr<CFileItem>& item, + const std::string& artType) + : CVideoItemArtworkHandler(item, artType) + { + } + + std::vector<std::string> GetRemoteArt() const override; + std::string GetLocalArt() const override; + + std::string GetDefaultIcon() const override { return "DefaultVideo.png"; } + + void AddItemPathToFileBrowserSources(std::vector<CMediaSource>& sources) override; +}; + +std::vector<std::string> CVideoItemArtworkMovieSetHandler::GetRemoteArt() const +{ + CVideoDatabase videodb; + if (!videodb.Open()) + { + CLog::LogF(LOGERROR, "Cannot open video database!"); + return {}; + } + + std::vector<std::string> remoteArt; + const std::string baseDir = + StringUtils::Format("videodb://movies/sets/{}", m_item->GetVideoInfoTag()->m_iDbId); + CFileItemList items; + if (videodb.GetMoviesNav(baseDir, items)) + { + for (const auto& item : items) + { + CVideoInfoTag* videotag = item->GetVideoInfoTag(); + videotag->m_strPictureURL.Parse(); + videotag->m_strPictureURL.GetThumbUrls(remoteArt, "set." + m_artType, -1, true); + } + } + return remoteArt; +} + +std::string CVideoItemArtworkMovieSetHandler::GetLocalArt() const +{ + std::string localArt; + const std::string infoFolder = + VIDEO::CVideoInfoScanner::GetMovieSetInfoFolder(m_item->GetLabel()); + if (!infoFolder.empty()) + { + CFileItemList availableArtFiles; + CDirectory::GetDirectory(infoFolder, availableArtFiles, + CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(), + DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_READ_CACHE | DIR_FLAG_NO_FILE_INFO); + for (const auto& artFile : availableArtFiles) + { + std::string candidate = URIUtils::GetFileName(artFile->GetDynPath()); + URIUtils::RemoveExtension(candidate); + if (StringUtils::EqualsNoCase(candidate, m_artType)) + { + localArt = artFile->GetDynPath(); + break; + } + } + } + return localArt; +} + +void CVideoItemArtworkMovieSetHandler::AddItemPathToFileBrowserSources( + std::vector<CMediaSource>& sources) +{ + AddItemPathStringToFileBrowserSources( + sources, VIDEO::CVideoInfoScanner::GetMovieSetInfoFolder(m_item->GetLabel()), + g_localizeStrings.Get(36041) /* * Item folder */); + AddItemPathStringToFileBrowserSources( + sources, + CServiceBroker::GetSettingsComponent()->GetSettings()->GetString( + CSettings::SETTING_VIDEOLIBRARY_MOVIESETSFOLDER), + "* " + g_localizeStrings.Get(20226) /* Movie set information folder */); +} + +//------------------------------------------------------------------------------------------------- +// CVideoItemArtworkFanartHandler (Handler for all media types, to manage fanart art type) +//------------------------------------------------------------------------------------------------- + +class CVideoItemArtworkFanartHandler : public CVideoItemArtworkHandler +{ +public: + explicit CVideoItemArtworkFanartHandler(const std::shared_ptr<CFileItem>& item, + const std::string& artType) + : CVideoItemArtworkHandler(item, artType) + { + // Ensure the fanart is unpacked + m_item->GetVideoInfoTag()->m_fanart.Unpack(); + } + + std::string GetCurrentArt() const override; + std::vector<std::string> GetRemoteArt() const override; + std::string GetLocalArt() const override; + + std::string GetDefaultIcon() const override { return "DefaultPicture.png"; } + bool SupportsFlippedArt() const override { return true; } + + std::string UpdateEmbeddedArt(const std::string& art) override; + std::string UpdateRemoteArt(const std::vector<std::string>& art, int index) override; +}; + +std::string CVideoItemArtworkFanartHandler::GetCurrentArt() const +{ + return m_item->GetArt("fanart"); +} + +std::vector<std::string> CVideoItemArtworkFanartHandler::GetRemoteArt() const +{ + std::vector<std::string> remoteArt; + const CVideoInfoTag* videoTag = m_item->GetVideoInfoTag(); + for (unsigned int i = 0; i < videoTag->m_fanart.GetNumFanarts(); ++i) + { + const std::string thumb = videoTag->m_fanart.GetPreviewURL(i); + if (URIUtils::IsProtocol(thumb, "image")) + continue; + + remoteArt.emplace_back(CTextureUtils::GetWrappedThumbURL(thumb)); + } + return remoteArt; +} + +std::string CVideoItemArtworkFanartHandler::GetLocalArt() const +{ + return m_item->GetLocalFanart(); +} + +std::string CVideoItemArtworkFanartHandler::UpdateEmbeddedArt(const std::string& art) +{ + CVideoDatabase videodb; + if (!videodb.Open()) + { + CLog::LogF(LOGERROR, "Cannot open video database!"); + return art; + } + + CVideoInfoTag* videoTag = m_item->GetVideoInfoTag(); + const int currentTag = videoTag->m_fanart.GetNumFanarts(); + int matchingTag = -1; + for (int i = 0; i < currentTag; ++i) + { + if (URIUtils::IsProtocol(videoTag->m_fanart.GetImageURL(i), "image")) + matchingTag = i; + } + + if (matchingTag != -1) + { + videoTag->m_fanart.AddFanart(art, "", ""); + matchingTag = currentTag; + } + + videoTag->m_fanart.SetPrimaryFanart(matchingTag); + videodb.UpdateFanart(*m_item, m_item->GetVideoContentType()); + return art; +} + +std::string CVideoItemArtworkFanartHandler::UpdateRemoteArt(const std::vector<std::string>& art, + int index) +{ + CVideoInfoTag* videoTag = m_item->GetVideoInfoTag(); + + CVideoDatabase videodb; + if (!videodb.Open()) + { + CLog::LogF(LOGERROR, "Cannot open video database!"); + } + else + { + videoTag->m_fanart.SetPrimaryFanart(index); + videodb.UpdateFanart(*m_item, m_item->GetVideoContentType()); + } + return videoTag->m_fanart.GetImageURL(); +} + +} // unnamed namespace + +//------------------------------------------------------------------------------------------------- +// IVideoItemArtworkHandlerFactory +//------------------------------------------------------------------------------------------------- + +std::unique_ptr<IVideoItemArtworkHandler> IVideoItemArtworkHandlerFactory::Create( + const std::shared_ptr<CFileItem>& item, + const std::string& mediaType, + const std::string& artType) +{ + std::unique_ptr<IVideoItemArtworkHandler> artHandler; + + if (artType == "fanart" && mediaType != MediaTypeVideoCollection) + artHandler = std::make_unique<CVideoItemArtworkFanartHandler>(item, artType); + else if (mediaType == MediaTypeArtist) + artHandler = std::make_unique<CVideoItemArtworkArtistHandler>(item, artType); + else if (mediaType == "actor") + artHandler = std::make_unique<CVideoItemArtworkActorHandler>(item, artType); + else if (mediaType == MediaTypeSeason) + artHandler = std::make_unique<CVideoItemArtworkSeasonHandler>(item, artType); + else if (mediaType == MediaTypeVideoCollection) + artHandler = std::make_unique<CVideoItemArtworkMovieSetHandler>(item, artType); + else + artHandler = std::make_unique<CVideoItemArtworkHandler>(item, artType); + + return artHandler; +} diff --git a/xbmc/video/VideoItemArtworkHandler.h b/xbmc/video/VideoItemArtworkHandler.h new file mode 100644 index 0000000000..01613ef7d0 --- /dev/null +++ b/xbmc/video/VideoItemArtworkHandler.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include <memory> +#include <string> +#include <vector> + +class CFileItem; +class CMediaSource; + +namespace VIDEO +{ +class IVideoItemArtworkHandler +{ +public: + virtual ~IVideoItemArtworkHandler() = default; + + virtual std::string GetCurrentArt() const = 0; + + virtual std::string GetEmbeddedArt() const { return {}; } + virtual std::vector<std::string> GetRemoteArt() const { return {}; } + virtual std::string GetLocalArt() const { return {}; } + + virtual std::string GetDefaultIcon() const = 0; + virtual bool SupportsFlippedArt() const { return false; } + + virtual void AddItemPathToFileBrowserSources(std::vector<CMediaSource>& sources) {} + + virtual std::string UpdateEmbeddedArt(const std::string& art) { return art; } + virtual std::string UpdateRemoteArt(const std::vector<std::string>& art, int index) + { + return art[index]; + } + + virtual void PersistArt(const std::string& art) = 0; +}; + +class IVideoItemArtworkHandlerFactory +{ +public: + static std::unique_ptr<IVideoItemArtworkHandler> Create(const std::shared_ptr<CFileItem>& item, + const std::string& mediaType, + const std::string& artType); +}; + +} // namespace VIDEO diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp index 233fe7606a..2ded282183 100644 --- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp @@ -41,7 +41,6 @@ #include "settings/SettingsComponent.h" #include "settings/lib/Setting.h" #include "storage/MediaManager.h" -#include "utils/FileExtensionProvider.h" #include "utils/FileUtils.h" #include "utils/SortUtils.h" #include "utils/StringUtils.h" @@ -50,10 +49,10 @@ #include "video/VideoDbUrl.h" #include "video/VideoInfoScanner.h" #include "video/VideoInfoTag.h" +#include "video/VideoItemArtworkHandler.h" #include "video/VideoLibraryQueue.h" #include "video/VideoThumbLoader.h" #include "video/VideoUtils.h" -#include "video/tags/VideoTagLoaderFFmpeg.h" #include "video/windows/GUIWindowVideoNav.h" #include <iterator> @@ -879,184 +878,24 @@ std::string CGUIDialogVideoInfo::ChooseArtType(const CFileItem &videoItem) void CGUIDialogVideoInfo::OnGetArt() { - bool finished = false; - while (!finished) + if (ChooseAndManageVideoItemArtwork(m_movieItem)) { - if (ManageVideoItemArtwork(m_movieItem, m_movieItem->GetVideoInfoTag()->m_type, finished)) - { - m_hasUpdatedThumb = true; - - // Update our screen - Update(); - } - }; -} + m_hasUpdatedThumb = true; -namespace -{ -std::string GetEmbeddedArt(const std::string& fileNameAndPath, const std::string& artType) -{ - std::string embeddedArt; - if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( - CSettings::SETTING_MYVIDEOS_USETAGS)) - { - if (URIUtils::HasExtension(fileNameAndPath, ".mkv") || - URIUtils::HasExtension(fileNameAndPath, ".mp4") || - URIUtils::HasExtension(fileNameAndPath, ".avi") || - URIUtils::HasExtension(fileNameAndPath, ".m4v")) - { - CFileItem item(fileNameAndPath, false); - CVideoTagLoaderFFmpeg loader(item, nullptr, false); - CVideoInfoTag tag; - loader.Load(tag, false, nullptr); - for (const auto& it : tag.m_coverArt) - { - if (it.m_type == artType) - { - embeddedArt = CTextureUtils::GetWrappedImageURL(fileNameAndPath, "video_" + artType); - break; - } - } - } + // Update our screen + Update(); } - return embeddedArt; } -} // unnamed namespace - -// Allow user to select a Fanart void CGUIDialogVideoInfo::OnGetFanart() { - CFileItemList items; - - // Ensure the fanart is unpacked - m_movieItem->GetVideoInfoTag()->m_fanart.Unpack(); - - if (m_movieItem->HasArt("fanart")) - { - CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false)); - itemCurrent->SetArt("thumb", m_movieItem->GetArt("fanart")); - itemCurrent->SetArt("icon", "DefaultPicture.png"); - itemCurrent->SetLabel(g_localizeStrings.Get(20440)); - items.Add(itemCurrent); - } - - const std::string embeddedArt = - GetEmbeddedArt(m_movieItem->GetVideoInfoTag()->m_strFileNameAndPath, "fanart"); - if (!embeddedArt.empty()) - { - const auto itemEmbedded = std::make_shared<CFileItem>("fanart://Embedded", false); - itemEmbedded->SetArt("thumb", embeddedArt); - itemEmbedded->SetLabel(g_localizeStrings.Get(13520)); - items.Add(itemEmbedded); - } - - // Grab the thumbnails from the web - for (unsigned int i = 0; i < m_movieItem->GetVideoInfoTag()->m_fanart.GetNumFanarts(); i++) - { - if (URIUtils::IsProtocol(m_movieItem->GetVideoInfoTag()->m_fanart.GetPreviewURL(i), "image")) - continue; - std::string strItemPath = StringUtils::Format("fanart://Remote{}", i); - CFileItemPtr item(new CFileItem(strItemPath, false)); - std::string thumb = m_movieItem->GetVideoInfoTag()->m_fanart.GetPreviewURL(i); - item->SetArt("thumb", CTextureUtils::GetWrappedThumbURL(thumb)); - item->SetArt("icon", "DefaultPicture.png"); - item->SetLabel(g_localizeStrings.Get(20441)); - - //! @todo Do we need to clear the cached image? - // CServiceBroker::GetTextureCache()->ClearCachedImage(thumb); - items.Add(item); - } - - CFileItem item(*m_movieItem->GetVideoInfoTag()); - std::string strLocal = item.GetLocalFanart(); - if (!strLocal.empty()) + if (ManageVideoItemArtwork(m_movieItem, m_movieItem->GetVideoInfoTag()->m_type, "fanart")) { - CFileItemPtr itemLocal(new CFileItem("fanart://Local",false)); - itemLocal->SetArt("thumb", strLocal); - itemLocal->SetArt("icon", "DefaultPicture.png"); - itemLocal->SetLabel(g_localizeStrings.Get(20438)); + m_hasUpdatedThumb = true; - //! @todo Do we need to clear the cached image? - CServiceBroker::GetTextureCache()->ClearCachedImage(strLocal); - items.Add(itemLocal); - } - else - { - CFileItemPtr itemNone(new CFileItem("fanart://None", false)); - itemNone->SetArt("icon", "DefaultPicture.png"); - itemNone->SetLabel(g_localizeStrings.Get(20439)); - items.Add(itemNone); + // Update our screen + Update(); } - - std::string result; - VECSOURCES sources(*CMediaSourceSettings::GetInstance().GetSources("video")); - AddItemPathToFileBrowserSources(sources, item); - CServiceBroker::GetMediaManager().GetLocalDrives(sources); - bool flip=false; - if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20437), result, &flip, 20445) || - StringUtils::EqualsNoCase(result, "fanart://Current")) - return; // user cancelled - - if (StringUtils::EqualsNoCase(result, "fanart://Local")) - result = strLocal; - - if (StringUtils::EqualsNoCase(result, "fanart://Embedded")) - { - unsigned int current = m_movieItem->GetVideoInfoTag()->m_fanart.GetNumFanarts(); - int found = -1; - for (size_t i = 0; i < current; ++i) - if (URIUtils::IsProtocol(m_movieItem->GetVideoInfoTag()->m_fanart.GetImageURL(), "image")) - found = i; - if (found != -1) - { - m_movieItem->GetVideoInfoTag()->m_fanart.AddFanart(embeddedArt, "", ""); - found = current; - } - - m_movieItem->GetVideoInfoTag()->m_fanart.SetPrimaryFanart(found); - - CVideoDatabase db; - if (db.Open()) - { - db.UpdateFanart(*m_movieItem, m_movieItem->GetVideoContentType()); - db.Close(); - } - result = embeddedArt; - } - - if (StringUtils::StartsWith(result, "fanart://Remote")) - { - int iFanart = atoi(result.substr(15).c_str()); - // set new primary fanart, and update our database accordingly - m_movieItem->GetVideoInfoTag()->m_fanart.SetPrimaryFanart(iFanart); - CVideoDatabase db; - if (db.Open()) - { - db.UpdateFanart(*m_movieItem, m_movieItem->GetVideoContentType()); - db.Close(); - } - result = m_movieItem->GetVideoInfoTag()->m_fanart.GetImageURL(); - } - else if (StringUtils::EqualsNoCase(result, "fanart://None") || !CFileUtils::Exists(result)) - result.clear(); - - // set the fanart image - if (flip && !result.empty()) - result = CTextureUtils::GetWrappedImageURL(result, "", "flipped"); - CVideoDatabase db; - if (db.Open()) - { - db.SetArtForItem(m_movieItem->GetVideoInfoTag()->m_iDbId, m_movieItem->GetVideoInfoTag()->m_type, "fanart", result); - db.Close(); - } - - CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show - m_movieItem->SetArt("fanart", result); - m_hasUpdatedThumb = true; - - // Update our screen - Update(); } void CGUIDialogVideoInfo::OnSetUserrating() const @@ -1105,45 +944,6 @@ std::string CGUIDialogVideoInfo::GetThumbnail() const return m_movieItem->GetArt("thumb"); } -namespace -{ -std::string GetItemPathForBrowserSource(const CFileItem& item) -{ - if (!item.HasVideoInfoTag()) - return ""; - - std::string itemDir = item.GetVideoInfoTag()->m_basePath; - //season - if (itemDir.empty()) - itemDir = item.GetVideoInfoTag()->GetPath(); - - CFileItem itemTmp(itemDir, false); - if (itemTmp.IsVideo()) - itemDir = URIUtils::GetParentPath(itemDir); - - return itemDir; -} - -void AddItemPathStringToFileBrowserSources(VECSOURCES& sources, - const std::string& itemDir, const std::string& label) -{ - if (!itemDir.empty() && CDirectory::Exists(itemDir)) - { - CMediaSource itemSource; - itemSource.strName = label; - itemSource.strPath = itemDir; - sources.push_back(itemSource); - } -} -} // namespace - -void CGUIDialogVideoInfo::AddItemPathToFileBrowserSources(VECSOURCES& sources, - const CFileItem& item) -{ - std::string itemDir = GetItemPathForBrowserSource(item); - AddItemPathStringToFileBrowserSources(sources, itemDir, g_localizeStrings.Get(36041)); -} - int CGUIDialogVideoInfo::ManageVideoItem(const std::shared_ptr<CFileItem>& item) { if (item == nullptr || !item->IsVideoDb() || !item->HasVideoInfoTag() || item->GetVideoInfoTag()->m_iDbId < 0) @@ -1259,7 +1059,7 @@ int CGUIDialogVideoInfo::ManageVideoItem(const std::shared_ptr<CFileItem>& item) break; case CONTEXT_BUTTON_SET_ART: - result = ManageVideoItemArtwork(item, type); + result = ChooseAndManageVideoItemArtwork(item); break; case CONTEXT_BUTTON_MOVIESET_ADD_REMOVE_ITEMS: @@ -1878,128 +1678,51 @@ bool CGUIDialogVideoInfo::RemoveItemsFromTag(const std::shared_ptr<CFileItem>& t return true; } -namespace -{ -std::string FindLocalMovieSetArtworkFile(const CFileItemPtr& item, const std::string& artType) -{ - std::string infoFolder = VIDEO::CVideoInfoScanner::GetMovieSetInfoFolder(item->GetLabel()); - if (infoFolder.empty()) - return ""; - - CFileItemList availableArtFiles; - CDirectory::GetDirectory(infoFolder, availableArtFiles, - CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(), - DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_READ_CACHE | DIR_FLAG_NO_FILE_INFO); - for (const auto& artFile : availableArtFiles) - { - std::string candidate = URIUtils::GetFileName(artFile->GetPath()); - URIUtils::RemoveExtension(candidate); - if (StringUtils::EqualsNoCase(candidate, artType)) - return artFile->GetPath(); - } - return ""; -} -} // namespace - -bool CGUIDialogVideoInfo::ManageVideoItemArtwork(const std::shared_ptr<CFileItem>& item, - const MediaType& type) +bool CGUIDialogVideoInfo::ChooseAndManageVideoItemArtwork(const std::shared_ptr<CFileItem>& item) { bool result = false; - bool finished = false; - while (!finished) + std::string artType; + do { - result = ManageVideoItemArtwork(item, type, finished); - } + artType = ChooseArtType(*item); + if (!artType.empty()) + result = ManageVideoItemArtwork(item, item->GetVideoInfoTag()->m_type, artType); + + } while (!artType.empty()); return result; } bool CGUIDialogVideoInfo::ManageVideoItemArtwork(const std::shared_ptr<CFileItem>& item, - const MediaType& type, - bool& finished) + const std::string& mediaType) { - finished = true; + // When not selecting art type, default type to "thumb". + return ManageVideoItemArtwork(item, mediaType, "thumb"); +} - if (item == nullptr || !item->HasVideoInfoTag() || type.empty()) +bool CGUIDialogVideoInfo::ManageVideoItemArtwork(const std::shared_ptr<CFileItem>& item, + const MediaType& mediaType, + const std::string& artType) +{ + if (item == nullptr || !item->HasVideoInfoTag() || mediaType.empty() || artType.empty()) return false; - CVideoDatabase videodb; - if (!videodb.Open()) - return false; + const std::unique_ptr<VIDEO::IVideoItemArtworkHandler> artHandler = + VIDEO::IVideoItemArtworkHandlerFactory::Create(item, mediaType, artType); - // Grab the thumbnails from the web CFileItemList items; - CFileItemPtr noneitem(new CFileItem("thumb://None", false)); - std::string currentThumb; - int idArtist = -1; - std::string artistPath; - std::string artistOldPath; - std::string artType = "thumb"; - if (type == MediaTypeArtist) - { - CMusicDatabase musicdb; - if (musicdb.Open()) - { - idArtist = musicdb.GetArtistByName(item->GetLabel()); // Fails when name not unique - if (idArtist >= 0 ) - { - // Get artist paths - possible locations for thumb - while music db open - musicdb.GetOldArtistPath(idArtist, artistOldPath); // Old artist path, local to music files - CArtist artist; - musicdb.GetArtist(idArtist, artist); // Need name and mbid for artist folder name - musicdb.GetArtistPath(artist, artistPath); // Artist path in artist info folder - - currentThumb = musicdb.GetArtForItem(idArtist, MediaTypeArtist, "thumb"); - if (currentThumb.empty()) - currentThumb = videodb.GetArtForItem(item->GetVideoInfoTag()->m_iDbId, item->GetVideoInfoTag()->m_type, artType); - } - } - } - else if (type == "actor") - { - currentThumb = videodb.GetArtForItem(item->GetVideoInfoTag()->m_iDbId, item->GetVideoInfoTag()->m_type, artType); - } - else - { // SEASON, SHOW, SET - - // We want to re-open the art type selection dialog after selecting an image for the type - // until user canceled the art type selection dialog, controlled via 'finished' value by - // the caller of this method. - - artType = ChooseArtType(*item); - if (artType.empty()) - { - finished = true; - return false; - } - finished = false; - - if (artType == "fanart" && type != MediaTypeVideoCollection) - { - const bool result = OnGetFanart(item); - return result; - } - - if (item->HasArt(artType)) - currentThumb = item->GetArt(artType); - else if ((artType == "poster" || artType == "banner") && item->HasArt("thumb")) - currentThumb = item->GetArt("thumb"); - } - - if (!currentThumb.empty()) + const std::string currentArt = artHandler->GetCurrentArt(); + if (!currentArt.empty()) { - CFileItemPtr item(new CFileItem("thumb://Current", false)); - item->SetArt("thumb", currentThumb); - item->SetLabel(g_localizeStrings.Get(13512)); - items.Add(item); + const auto itemCurrent = std::make_shared<CFileItem>("thumb://Current", false); + itemCurrent->SetArt("thumb", currentArt); + itemCurrent->SetLabel(g_localizeStrings.Get(13512)); + items.Add(itemCurrent); } - noneitem->SetArt("icon", item->m_bIsFolder ? "DefaultFolder.png" : "DefaultPicture.png"); - noneitem->SetLabel(g_localizeStrings.Get(13515)); - const std::string embeddedArt = - GetEmbeddedArt(item->GetVideoInfoTag()->m_strFileNameAndPath, artType); + const std::string embeddedArt = artHandler->GetEmbeddedArt(); if (!embeddedArt.empty()) { const auto itemEmbedded = std::make_shared<CFileItem>("thumb://Embedded", false); @@ -2008,180 +1731,75 @@ bool CGUIDialogVideoInfo::ManageVideoItemArtwork(const std::shared_ptr<CFileItem items.Add(itemEmbedded); } - std::string localThumb; - - bool local = false; - std::vector<std::string> thumbs; - if (type != MediaTypeArtist) + std::vector<std::string> remoteArt = artHandler->GetRemoteArt(); + for (size_t i = 0; i < remoteArt.size(); ++i) { - CVideoInfoTag tag; - if (type == MediaTypeSeason) - { - videodb.GetTvShowInfo("", tag, item->GetVideoInfoTag()->m_iIdShow); - tag.m_strPictureURL.Parse(); - tag.m_strPictureURL.GetThumbUrls(thumbs, artType, item->GetVideoInfoTag()->m_iSeason); - } - else if (type == MediaTypeVideoCollection) - { - CFileItemList items; - std::string baseDir = - StringUtils::Format("videodb://movies/sets/{}", item->GetVideoInfoTag()->m_iDbId); - if (videodb.GetMoviesNav(baseDir, items)) - { - for (int i=0; i < items.Size(); i++) - { - CVideoInfoTag* pTag = items[i]->GetVideoInfoTag(); - pTag->m_strPictureURL.Parse(); - pTag->m_strPictureURL.GetThumbUrls(thumbs, "set." + artType, -1, true); - } - } - } - else - { - tag = *item->GetVideoInfoTag(); - tag.m_strPictureURL.Parse(); - tag.m_strPictureURL.GetThumbUrls(thumbs, artType); - } + const auto itemRemote = + std::make_shared<CFileItem>(StringUtils::Format("thumb://Remote{0}", i), false); + itemRemote->SetArt("thumb", remoteArt[i]); + itemRemote->SetArt("icon", "DefaultPicture.png"); + itemRemote->SetLabel(g_localizeStrings.Get(13513)); + items.Add(itemRemote); - for (size_t i = 0; i < thumbs.size(); i++) - { - CFileItemPtr item(new CFileItem(StringUtils::Format("thumb://Remote{0}", i), false)); - item->SetArt("thumb", thumbs[i]); - item->SetArt("icon", "DefaultPicture.png"); - item->SetLabel(g_localizeStrings.Get(13513)); - items.Add(item); - - //! @todo Do we need to clear the cached image? - // CServiceBroker::GetTextureCache()->ClearCachedImage(thumbs[i]); - } - - if (type == "actor") - { - std::string picturePath; - std::string strThumb = URIUtils::AddFileToFolder(picturePath, "folder.jpg"); - if (CFileUtils::Exists(strThumb)) - { - CFileItemPtr pItem(new CFileItem(strThumb,false)); - pItem->SetLabel(g_localizeStrings.Get(13514)); - pItem->SetArt("thumb", strThumb); - items.Add(pItem); - local = true; - } - else - noneitem->SetArt("icon", "DefaultActor.png"); - } - else if (type == MediaTypeVideoCollection) - { - std::string localFile = FindLocalMovieSetArtworkFile(item, artType); - if (!localFile.empty()) - { - CFileItemPtr pItem(new CFileItem(localFile, false)); - pItem->SetLabel(g_localizeStrings.Get(13514)); - pItem->SetArt("thumb", localFile); - items.Add(pItem); - local = true; - } - else - noneitem->SetArt("icon", "DefaultVideo.png"); - } - else - { - localThumb = CVideoThumbLoader::GetLocalArt(*item, artType); - if (!localThumb.empty()) - { - const auto localitem = std::make_shared<CFileItem>("thumb://Local", false); - localitem->SetArt("thumb", localThumb); - localitem->SetArt("icon", "DefaultPicture.png"); - localitem->SetLabel(g_localizeStrings.Get(13514)); - items.Add(localitem); - } - else - noneitem->SetArt("icon", "DefaultPicture.png"); - } + //! @todo Do we need to clear the cached image? + // CServiceBroker::GetTextureCache()->ClearCachedImage(remoteArt[i]); } - else - { - std::string strThumb; - bool existsThumb = false; - // First look for artist thumb in the primary location - if (!artistPath.empty()) - { - strThumb = URIUtils::AddFileToFolder(artistPath, "folder.jpg"); - existsThumb = CFileUtils::Exists(strThumb); - } - // If not there fall back local to music files (historic location for those album artists with a unique folder) - if (!existsThumb && !artistOldPath.empty()) - { - strThumb = URIUtils::AddFileToFolder(artistOldPath, "folder.jpg"); - existsThumb = CFileUtils::Exists(strThumb); - } - if (existsThumb) - { - CFileItemPtr pItem(new CFileItem(strThumb, false)); - pItem->SetLabel(g_localizeStrings.Get(13514)); - pItem->SetArt("thumb", strThumb); - items.Add(pItem); - local = true; - } - else - noneitem->SetArt("icon", "DefaultArtist.png"); + const std::string localArt = artHandler->GetLocalArt(); + if (!localArt.empty()) + { + const auto itemLocal = std::make_shared<CFileItem>("thumb://Local", false); + itemLocal->SetLabel(g_localizeStrings.Get(13514)); + itemLocal->SetArt("thumb", localArt); + items.Add(itemLocal); } - if (!local) - items.Add(noneitem); + const auto itemNone = std::make_shared<CFileItem>("thumb://None", false); + itemNone->SetLabel(g_localizeStrings.Get(13515)); + itemNone->SetArt("icon", artHandler->GetDefaultIcon()); + items.Add(itemNone); std::string result; - VECSOURCES sources=*CMediaSourceSettings::GetInstance().GetSources("video"); + std::vector<CMediaSource> sources = *CMediaSourceSettings::GetInstance().GetSources("video"); CServiceBroker::GetMediaManager().GetLocalDrives(sources); - if (type == MediaTypeVideoCollection) - { - AddItemPathStringToFileBrowserSources(sources, - VIDEO::CVideoInfoScanner::GetMovieSetInfoFolder(item->GetLabel()), - g_localizeStrings.Get(36041)); - AddItemPathStringToFileBrowserSources(sources, - CServiceBroker::GetSettingsComponent()->GetSettings()->GetString( - CSettings::SETTING_VIDEOLIBRARY_MOVIESETSFOLDER), - "* " + g_localizeStrings.Get(20226)); - } - else - AddItemPathToFileBrowserSources(sources, *item); + artHandler->AddItemPathToFileBrowserSources(sources); - if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(13511), result)) - return false; // user cancelled + bool flip = false; + if (!CGUIDialogFileBrowser::ShowAndGetImage( + items, sources, g_localizeStrings.Get(13511) /* Choose art */, result, + artHandler->SupportsFlippedArt() ? &flip : nullptr, 39123 /* Artwork */)) + return false; // user cancelled if (result == "thumb://Current") - result = currentThumb; // user chose the one they have + result = currentArt; // user chose the one they have if (result == "thumb://Local") - result = localThumb; + result = localArt; if (result == "thumb://Embedded") - result = embeddedArt; + result = artHandler->UpdateEmbeddedArt(embeddedArt); // delete the thumbnail if that's what the user wants, else overwrite with the // new thumbnail if (result == "thumb://None") + { result.clear(); + } else if (StringUtils::StartsWith(result, "thumb://Remote")) { - int number = atoi(StringUtils::Mid(result, 14).c_str()); - result = thumbs[number]; + const int index = std::atoi(StringUtils::Mid(result, 14).c_str()); + result = artHandler->UpdateRemoteArt(remoteArt, index); } + // flip selected image, if user wants it + if (!result.empty() && flip) + result = CTextureUtils::GetWrappedImageURL(result, "", "flipped"); + // write the selected artwork to the database - if (type != MediaTypeArtist || idArtist < 0) - { - videodb.SetArtForItem(item->GetVideoInfoTag()->m_iDbId, item->GetVideoInfoTag()->m_type, artType, result); - } - else - { - CMusicDatabase musicdb; - if (musicdb.Open()) - musicdb.SetArtForItem(idArtist, MediaTypeArtist, artType, result); - } + artHandler->PersistArt(result); item->SetArt(artType, result); + if (item->HasProperty("set_folder_thumb")) { // have a folder thumb to set as well @@ -2310,59 +1928,6 @@ bool CGUIDialogVideoInfo::LinkMovieToTvShow(const std::shared_ptr<CFileItem>& it return false; } -bool CGUIDialogVideoInfo::OnGetFanart(const std::shared_ptr<CFileItem>& videoItem) -{ - if (videoItem == nullptr || !videoItem->HasVideoInfoTag()) - return false; - - // update the db - CVideoDatabase videodb; - if (!videodb.Open()) - return false; - - CVideoThumbLoader loader; - CFileItem item(*videoItem); - loader.LoadItem(&item); - - CFileItemList items; - if (item.HasArt("fanart")) - { - CFileItemPtr itemCurrent(new CFileItem("fanart://Current", false)); - itemCurrent->SetArt("thumb", item.GetArt("fanart")); - itemCurrent->SetLabel(g_localizeStrings.Get(20440)); - items.Add(itemCurrent); - } - - // add the none option - { - CFileItemPtr itemNone(new CFileItem("fanart://None", false)); - itemNone->SetArt("icon", videoItem->m_bIsFolder ? "DefaultFolder.png" : "DefaultPicture.png"); - itemNone->SetLabel(g_localizeStrings.Get(20439)); - items.Add(itemNone); - } - - std::string result; - VECSOURCES sources(*CMediaSourceSettings::GetInstance().GetSources("video")); - CServiceBroker::GetMediaManager().GetLocalDrives(sources); - AddItemPathToFileBrowserSources(sources, item); - bool flip = false; - if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20437), result, &flip, 20445) || - StringUtils::EqualsNoCase(result, "fanart://Current")) - return false; - - else if (StringUtils::EqualsNoCase(result, "fanart://None") || !CFileUtils::Exists(result)) - result.clear(); - if (!result.empty() && flip) - result = CTextureUtils::GetWrappedImageURL(result, "", "flipped"); - - videodb.SetArtForItem(item.GetVideoInfoTag()->m_iDbId, item.GetVideoInfoTag()->m_type, "fanart", result); - - // clear view cache and reload images - CUtil::DeleteVideoDatabaseDirectoryCache(); - - return true; -} - void CGUIDialogVideoInfo::ShowFor(const CFileItem& item) { auto window = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowVideoNav>(WINDOW_VIDEO_NAV); diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.h b/xbmc/video/dialogs/GUIDialogVideoInfo.h index ef57ff68c3..06c703cc56 100644 --- a/xbmc/video/dialogs/GUIDialogVideoInfo.h +++ b/xbmc/video/dialogs/GUIDialogVideoInfo.h @@ -55,6 +55,7 @@ public: static bool AddItemsToTag(const std::shared_ptr<CFileItem>& tagItem); static bool RemoveItemsFromTag(const std::shared_ptr<CFileItem>& tagItem); + static bool ChooseAndManageVideoItemArtwork(const std::shared_ptr<CFileItem>& item); static bool ManageVideoItemArtwork(const std::shared_ptr<CFileItem>& item, const MediaType& type); static std::string GetLocalizedVideoType(const std::string &strType); @@ -96,11 +97,6 @@ protected: bool bRemove, CVideoDatabase& database); - /*! \brief Pop up a fanart chooser. Does not utilise remote URLs. - \param videoItem the item to choose fanart for. - */ - static bool OnGetFanart(const std::shared_ptr<CFileItem>& videoItem); - std::shared_ptr<CFileItem> m_movieItem; CFileItemList *m_castList; bool m_bViewReview = false; @@ -113,6 +109,6 @@ protected: private: static std::string ChooseArtType(const CFileItem& item); static bool ManageVideoItemArtwork(const std::shared_ptr<CFileItem>& item, - const MediaType& type, - bool& finished); + const MediaType& mediaType, + const std::string& artType); }; diff --git a/xbmc/video/tags/CMakeLists.txt b/xbmc/video/tags/CMakeLists.txt index ab289f864a..6b23664b36 100644 --- a/xbmc/video/tags/CMakeLists.txt +++ b/xbmc/video/tags/CMakeLists.txt @@ -1,9 +1,11 @@ -set(SOURCES VideoInfoTagLoaderFactory.cpp +set(SOURCES VideoTagExtractionHelper.cpp + VideoInfoTagLoaderFactory.cpp VideoTagLoaderFFmpeg.cpp VideoTagLoaderNFO.cpp VideoTagLoaderPlugin.cpp) set(HEADERS IVideoInfoTagLoader.h + VideoTagExtractionHelper.h VideoInfoTagLoaderFactory.h VideoTagLoaderFFmpeg.h VideoTagLoaderNFO.h diff --git a/xbmc/video/tags/VideoInfoTagLoaderFactory.cpp b/xbmc/video/tags/VideoInfoTagLoaderFactory.cpp index 00ed67a528..6f3c7fa009 100644 --- a/xbmc/video/tags/VideoInfoTagLoaderFactory.cpp +++ b/xbmc/video/tags/VideoInfoTagLoaderFactory.cpp @@ -9,12 +9,10 @@ #include "VideoInfoTagLoaderFactory.h" #include "FileItem.h" -#include "ServiceBroker.h" #include "VideoTagLoaderFFmpeg.h" #include "VideoTagLoaderNFO.h" #include "VideoTagLoaderPlugin.h" -#include "settings/Settings.h" -#include "settings/SettingsComponent.h" +#include "video/tags/VideoTagExtractionHelper.h" using namespace VIDEO; @@ -37,8 +35,7 @@ IVideoInfoTagLoader* CVideoInfoTagLoaderFactory::CreateLoader(const CFileItem& i return nfo; delete nfo; - if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MYVIDEOS_USETAGS) && - (item.IsType(".mkv") || item.IsType(".mp4") || item.IsType(".avi") || item.IsType(".m4v"))) + if (TAGS::CVideoTagExtractionHelper::IsExtractionSupportedFor(item)) { CVideoTagLoaderFFmpeg* ff = new CVideoTagLoaderFFmpeg(item, info, lookInFolder); if (ff->HasInfo()) diff --git a/xbmc/video/tags/VideoTagExtractionHelper.cpp b/xbmc/video/tags/VideoTagExtractionHelper.cpp new file mode 100644 index 0000000000..5ce567aed9 --- /dev/null +++ b/xbmc/video/tags/VideoTagExtractionHelper.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "VideoTagExtractionHelper.h" + +#include "FileItem.h" +#include "ServiceBroker.h" +#include "TextureDatabase.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "utils/URIUtils.h" +#include "video/VideoInfoTag.h" +#include "video/tags/VideoTagLoaderFFmpeg.h" + +using namespace VIDEO::TAGS; + +bool CVideoTagExtractionHelper::IsExtractionSupportedFor(const CFileItem& item) +{ + const std::string fileNameAndPath = item.GetVideoInfoTag()->m_strFileNameAndPath; + return CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( + CSettings::SETTING_MYVIDEOS_USETAGS) && + URIUtils::HasExtension(fileNameAndPath, ".mkv|.mp4|.avi|.m4v"); +} + +std::string CVideoTagExtractionHelper::ExtractEmbeddedArtFor(const CFileItem& item, + const std::string& artType) +{ + CVideoTagLoaderFFmpeg loader(item, nullptr, false); + CVideoInfoTag tag; + loader.Load(tag, false, nullptr); + for (const auto& it : tag.m_coverArt) + { + if (it.m_type == artType) + { + return CTextureUtils::GetWrappedImageURL(item.GetVideoInfoTag()->m_strFileNameAndPath, + "video_" + artType); + } + } + return {}; +} diff --git a/xbmc/video/tags/VideoTagExtractionHelper.h b/xbmc/video/tags/VideoTagExtractionHelper.h new file mode 100644 index 0000000000..1e6823e1cf --- /dev/null +++ b/xbmc/video/tags/VideoTagExtractionHelper.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include <string> + +class CFileItem; + +namespace VIDEO +{ +namespace TAGS +{ +class CVideoTagExtractionHelper +{ +public: + /*! + \brief Check whether tag extraction is supported for the given item. This is no + check whether the video denoted by the item actually contains any tags. There is also a Kodi + setting for enabling video tag support that is taken into consideration by the implementation of + this function. + \param item [in] the item denoting a video file. + \return True if tag support is enabled and extraction is supported for the given file type. + */ + static bool IsExtractionSupportedFor(const CFileItem& item); + + /*! + \brief Try to extract embedded art of given type from the given item denoting a video file. + \param item [in] the item. + \param artType The type of the art to extract (e.g. "fanart"). + \return The image URL of the embedded art if extraction was successful, false otherwise. + */ + static std::string ExtractEmbeddedArtFor(const CFileItem& item, const std::string& artType); +}; +} // namespace TAGS +} // namespace VIDEO diff --git a/xbmc/windowing/windows/WinSystemWin32DX.cpp b/xbmc/windowing/windows/WinSystemWin32DX.cpp index 4dff636464..52bea4ac99 100644 --- a/xbmc/windowing/windows/WinSystemWin32DX.cpp +++ b/xbmc/windowing/windows/WinSystemWin32DX.cpp @@ -25,11 +25,6 @@ #ifndef _M_X64 #include "utils/SystemInfo.h" #endif -#if _DEBUG -#pragma comment(lib, "detoursd.lib") -#else -#pragma comment(lib, "detours.lib") -#endif #pragma comment(lib, "dxgi.lib") #include <windows.h> #include <winnt.h> |