aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--addons/resource.language.en_gb/resources/strings.po7
-rw-r--r--cmake/modules/FindDav1d.cmake107
-rw-r--r--cmake/modules/FindDetours.cmake37
-rw-r--r--cmake/modules/FindFFMPEG.cmake27
-rw-r--r--cmake/modules/FindFlatBuffers.cmake3
-rw-r--r--cmake/modules/FindRapidJSON.cmake1
-rw-r--r--cmake/platform/windows/windows.cmake2
-rw-r--r--xbmc/guilib/guiinfo/SystemGUIInfo.cpp51
-rw-r--r--xbmc/guilib/guiinfo/SystemGUIInfo.h6
-rw-r--r--xbmc/platform/android/CMakeLists.txt2
-rw-r--r--xbmc/platform/android/GPUInfoAndroid.cpp24
-rw-r--r--xbmc/platform/android/GPUInfoAndroid.h22
-rw-r--r--xbmc/platform/darwin/ios-common/CMakeLists.txt2
-rw-r--r--xbmc/platform/darwin/ios-common/GPUInfoDarwinEmbed.cpp24
-rw-r--r--xbmc/platform/darwin/ios-common/GPUInfoDarwinEmbed.h22
-rw-r--r--xbmc/platform/darwin/osx/CMakeLists.txt2
-rw-r--r--xbmc/platform/darwin/osx/GPUInfoMacOS.cpp32
-rw-r--r--xbmc/platform/darwin/osx/GPUInfoMacOS.h22
-rw-r--r--xbmc/platform/darwin/osx/network/NetworkMacOS.mm2
-rw-r--r--xbmc/platform/freebsd/CMakeLists.txt2
-rw-r--r--xbmc/platform/freebsd/GPUInfoFreebsd.cpp24
-rw-r--r--xbmc/platform/freebsd/GPUInfoFreebsd.h22
-rw-r--r--xbmc/platform/linux/CMakeLists.txt2
-rw-r--r--xbmc/platform/linux/GPUInfoLinux.cpp24
-rw-r--r--xbmc/platform/linux/GPUInfoLinux.h22
-rw-r--r--xbmc/platform/posix/CMakeLists.txt2
-rw-r--r--xbmc/platform/posix/GPUInfoPosix.cpp52
-rw-r--r--xbmc/platform/posix/GPUInfoPosix.h22
-rw-r--r--xbmc/platform/win10/CMakeLists.txt2
-rw-r--r--xbmc/platform/win10/GPUInfoWin10.cpp35
-rw-r--r--xbmc/platform/win10/GPUInfoWin10.h25
-rw-r--r--xbmc/platform/win32/CMakeLists.txt2
-rw-r--r--xbmc/platform/win32/GPUInfoWin32.cpp35
-rw-r--r--xbmc/platform/win32/GPUInfoWin32.h25
-rw-r--r--xbmc/pvr/recordings/PVRRecordingsPath.cpp2
-rw-r--r--xbmc/utils/CMakeLists.txt2
-rw-r--r--xbmc/utils/GpuInfo.cpp35
-rw-r--r--xbmc/utils/GpuInfo.h66
-rw-r--r--xbmc/utils/test/CMakeLists.txt1
-rw-r--r--xbmc/utils/test/TestGPUInfo.cpp38
-rw-r--r--xbmc/video/CMakeLists.txt2
-rw-r--r--xbmc/video/VideoItemArtworkHandler.cpp554
-rw-r--r--xbmc/video/VideoItemArtworkHandler.h53
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoInfo.cpp589
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoInfo.h10
-rw-r--r--xbmc/video/tags/CMakeLists.txt4
-rw-r--r--xbmc/video/tags/VideoInfoTagLoaderFactory.cpp7
-rw-r--r--xbmc/video/tags/VideoTagExtractionHelper.cpp45
-rw-r--r--xbmc/video/tags/VideoTagExtractionHelper.h41
-rw-r--r--xbmc/windowing/windows/WinSystemWin32DX.cpp5
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>