diff options
65 files changed, 1027 insertions, 262 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/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/FindHarfBuzz.cmake b/cmake/modules/FindHarfBuzz.cmake index 6691136bbb..44b291c9b8 100644 --- a/cmake/modules/FindHarfBuzz.cmake +++ b/cmake/modules/FindHarfBuzz.cmake @@ -3,44 +3,37 @@ # ------------ # Finds the HarfBuzz library # -# This will define the following variables:: -# -# HARFBUZZ_FOUND - system has HarfBuzz -# HARFBUZZ_INCLUDE_DIRS - the HarfBuzz include directory -# HARFBUZZ_LIBRARIES - the HarfBuzz libraries -# -# and the following imported targets:: +# This will define the following target: # # HarfBuzz::HarfBuzz - The HarfBuzz library -if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_HARFBUZZ harfbuzz QUIET) -endif() - -find_path(HARFBUZZ_INCLUDE_DIR NAMES harfbuzz/hb-ft.h hb-ft.h - PATHS ${PC_HARFBUZZ_INCLUDEDIR} - ${PC_HARFBUZZ_INCLUDE_DIRS} - PATH_SUFFIXES harfbuzz) -find_library(HARFBUZZ_LIBRARY NAMES harfbuzz harfbuzz - PATHS ${PC_HARFBUZZ_LIBDIR}) +if(NOT TARGET HarfBuzz::HarfBuzz) + find_package(PkgConfig) + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_HARFBUZZ harfbuzz QUIET) + endif() -set(HARFBUZZ_VERSION ${PC_HARFBUZZ_VERSION}) + find_path(HARFBUZZ_INCLUDE_DIR NAMES harfbuzz/hb-ft.h hb-ft.h + HINTS ${PC_HARFBUZZ_INCLUDEDIR} + ${PC_HARFBUZZ_INCLUDE_DIRS} + PATH_SUFFIXES harfbuzz + NO_CACHE) + find_library(HARFBUZZ_LIBRARY NAMES harfbuzz + HINTS ${PC_HARFBUZZ_LIBDIR} + NO_CACHE) -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(HarfBuzz - REQUIRED_VARS HARFBUZZ_LIBRARY HARFBUZZ_INCLUDE_DIR - VERSION_VAR HARFBUZZ_VERSION) + set(HARFBUZZ_VERSION ${PC_HARFBUZZ_VERSION}) -if(HARFBUZZ_FOUND) - set(HARFBUZZ_LIBRARIES ${HARFBUZZ_LIBRARY}) - set(HARFBUZZ_INCLUDE_DIRS ${HARFBUZZ_INCLUDE_DIR}) + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(HarfBuzz + REQUIRED_VARS HARFBUZZ_LIBRARY HARFBUZZ_INCLUDE_DIR + VERSION_VAR HARFBUZZ_VERSION) - if(NOT TARGET HarfBuzz::HarfBuzz) + if(HARFBUZZ_FOUND) add_library(HarfBuzz::HarfBuzz UNKNOWN IMPORTED) set_target_properties(HarfBuzz::HarfBuzz PROPERTIES IMPORTED_LOCATION "${HARFBUZZ_LIBRARY}" INTERFACE_INCLUDE_DIRECTORIES "${HARFBUZZ_INCLUDE_DIR}") + set_property(GLOBAL APPEND PROPERTY INTERNAL_DEPS_PROP HarfBuzz::HarfBuzz) endif() endif() - -mark_as_advanced(HARFBUZZ_INCLUDE_DIR HARFBUZZ_LIBRARY) diff --git a/cmake/modules/FindLCMS2.cmake b/cmake/modules/FindLCMS2.cmake index d02515815d..73075d8997 100644 --- a/cmake/modules/FindLCMS2.cmake +++ b/cmake/modules/FindLCMS2.cmake @@ -3,46 +3,36 @@ # ----------- # Finds the LCMS Color Management library # -# This will define the following variables:: +# This will define the following target: # -# LCMS2_FOUND - system has LCMS Color Management -# LCMS2_INCLUDE_DIRS - the LCMS Color Management include directory -# LCMS2_LIBRARIES - the LCMS Color Management libraries -# LCMS2_DEFINITIONS - the LCMS Color Management definitions -# -# and the following imported targets:: -# -# LCMS2::LCMS2 - The LCMS Color Management library - -if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_LCMS2 lcms2>=2.10 QUIET) -endif() +# LCMS2::LCMS2 - The LCMS Color Management library -find_path(LCMS2_INCLUDE_DIR NAMES lcms2.h - PATHS ${PC_LCMS2_INCLUDEDIR}) -find_library(LCMS2_LIBRARY NAMES lcms2 liblcms2 - PATHS ${PC_LCMS2_LIBDIR}) +if(NOT TARGET LCMS2::LCMS2) + find_package(PkgConfig) + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_LCMS2 lcms2>=2.10 QUIET) + endif() -set(LCMS2_VERSION ${PC_LCMS2_VERSION}) + find_path(LCMS2_INCLUDE_DIR NAMES lcms2.h + HINTS ${PC_LCMS2_INCLUDEDIR} + NO_CACHE) + find_library(LCMS2_LIBRARY NAMES lcms2 liblcms2 + HINTS ${PC_LCMS2_LIBDIR} + NO_CACHE) -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(LCMS2 - REQUIRED_VARS LCMS2_LIBRARY LCMS2_INCLUDE_DIR - VERSION_VAR LCMS2_VERSION) + set(LCMS2_VERSION ${PC_LCMS2_VERSION}) -if(LCMS2_FOUND) - set(LCMS2_LIBRARIES ${LCMS2_LIBRARY}) - set(LCMS2_INCLUDE_DIRS ${LCMS2_INCLUDE_DIR}) - set(LCMS2_DEFINITIONS -DHAVE_LCMS2=1 -DCMS_NO_REGISTER_KEYWORD=1) + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(LCMS2 + REQUIRED_VARS LCMS2_LIBRARY LCMS2_INCLUDE_DIR + VERSION_VAR LCMS2_VERSION) - if(NOT TARGET LCMS2::LCMS2) + if(LCMS2_FOUND) add_library(LCMS2::LCMS2 UNKNOWN IMPORTED) set_target_properties(LCMS2::LCMS2 PROPERTIES IMPORTED_LOCATION "${LCMS2_LIBRARY}" INTERFACE_INCLUDE_DIRECTORIES "${LCMS2_INCLUDE_DIR}" - INTERFACE_COMPILE_DEFINITIONS HAVE_LCMS2=1) + INTERFACE_COMPILE_DEFINITIONS "HAVE_LCMS2=1;CMS_NO_REGISTER_KEYWORD=1") + set_property(GLOBAL APPEND PROPERTY INTERNAL_DEPS_PROP LCMS2::LCMS2) endif() endif() - -mark_as_advanced(LCMS2_INCLUDE_DIR LCMS2_LIBRARY) - diff --git a/cmake/modules/FindRapidJSON.cmake b/cmake/modules/FindRapidJSON.cmake index 5f6b290879..44a25b6193 100644 --- a/cmake/modules/FindRapidJSON.cmake +++ b/cmake/modules/FindRapidJSON.cmake @@ -3,10 +3,9 @@ # ----------- # Finds the RapidJSON library # -# This will define the following variables:: +# This will define the following target: # -# RapidJSON_FOUND - system has RapidJSON parser -# RapidJSON_INCLUDE_DIRS - the RapidJSON parser include directory +# RapidJSON::RapidJSON - The RapidJSON library # if(NOT TARGET RapidJSON::RapidJSON) @@ -64,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/modules/FindWaylandProtocolsWebOS.cmake b/cmake/modules/FindWaylandProtocolsWebOS.cmake index 979c34d660..041ea2bffa 100644 --- a/cmake/modules/FindWaylandProtocolsWebOS.cmake +++ b/cmake/modules/FindWaylandProtocolsWebOS.cmake @@ -4,24 +4,15 @@ # # This will define the following variables:: # -# WAYLANDPROTOCOLSWEBOS_FOUND - systm has wayland-webos-client # WAYLANDPROTOCOLSWEBOS_PROTOCOLSDIR - directory containing the additional webOS Wayland protocols # from the webos-wayland-extensions package -if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_WAYLAND_WEBOS_CLIENT wayland-webos-client>=1.0.0) -endif() -find_path(WAYLAND_PROTOCOLS_WEBOS_PROTOCOLDIR NAMES wayland-webos/webos-shell.xml - PATHS ${DEPENDS_PATH}/share) +find_path(WAYLANDPROTOCOLSWEBOS_PROTOCOLSDIR NAMES webos-shell.xml + PATH_SUFFIXES wayland-webos + PATHS ${DEPENDS_PATH}/share + REQUIRED) -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(WaylandProtocolsWebOS - REQUIRED_VARS WAYLAND_PROTOCOLS_WEBOS_PROTOCOLDIR - VERSION_VAR WAYLAND_WEBOS_SERVER_VERSION) - -if(WAYLANDPROTOCOLSWEBOS_FOUND) - # Promote to cache variables so all code can access it - set(WAYLANDPROTOCOLSWEBOS_PROTOCOLSDIR "${WAYLAND_PROTOCOLS_WEBOS_PROTOCOLDIR}/wayland-webos" CACHE INTERNAL "") -endif() +include(FindPackageMessage) +find_package_message(WaylandProtocolsWebOS "Found WaylandProtocols-WebOS: ${WAYLANDPROTOCOLSWEBOS_PROTOCOLSDIR}" "[${WAYLANDPROTOCOLSWEBOS_PROTOCOLSDIR}]") mark_as_advanced(WAYLANDPROTOCOLSWEBOS_PROTOCOLSDIR) 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/tools/depends/target/webos-wayland-extensions/Makefile b/tools/depends/target/webos-wayland-extensions/Makefile index 64d975bd78..90022df192 100644 --- a/tools/depends/target/webos-wayland-extensions/Makefile +++ b/tools/depends/target/webos-wayland-extensions/Makefile @@ -17,12 +17,6 @@ $(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE) .installed-$(PLATFORM): $(PLATFORM) mkdir -p $(PREFIX)/share/wayland-webos $(PREFIX)/lib/pkgconfig - rm -f ${PREFIX}/lib/pkgconfig/wayland-webos-client.pc - echo 'includedir=$(PREFIX)/include' >> ${PREFIX}/lib/pkgconfig/wayland-webos-client.pc - echo 'Name: wayland-webos-client' >> ${PREFIX}/lib/pkgconfig/wayland-webos-client.pc - echo 'Description: wayland-webos-client' >> ${PREFIX}/lib/pkgconfig/wayland-webos-client.pc - echo 'Version: 1.0.0' >> ${PREFIX}/lib/pkgconfig/wayland-webos-client.pc - cp $(PLATFORM)/protocol/webos-shell.xml $(PREFIX)/share/wayland-webos cp $(PLATFORM)/protocol/webos-foreign.xml $(PREFIX)/share/wayland-webos touch $@ diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp index ac4e0f7d41..32666e4ebc 100644 --- a/xbmc/GUIInfoManager.cpp +++ b/xbmc/GUIInfoManager.cpp @@ -6857,9 +6857,17 @@ const infomap container_str[] = {{ "property", CONTAINER_PROPERTY }, /// <p><hr> /// @skinning_v20 **[New Infolabel]** \link ListItem_HdrType `ListItem.HdrType`\endlink /// } +/// \table_row3{ <b>`ListItem.SongVideoURL`</b>, +/// \anchor ListItem_SongVideoURL +/// _string_, +/// @return Link to a video of a song +/// <p><hr> +/// @skinning_v21 **[New Infolabel]** \link ListItem_SongVideoURL `ListItem.SongVideoURL`\endlink +/// } /// \table_end /// /// ----------------------------------------------------------------------------- +// clang-format off const infomap listitem_labels[]= {{ "thumb", LISTITEM_THUMB }, { "icon", LISTITEM_ICON }, { "actualicon", LISTITEM_ACTUAL_ICON }, @@ -7069,7 +7077,9 @@ const infomap listitem_labels[]= {{ "thumb", LISTITEM_THUMB }, { "albumstatus", LISTITEM_ALBUMSTATUS }, { "isautoupdateable", LISTITEM_ISAUTOUPDATEABLE }, { "hdrtype", LISTITEM_VIDEO_HDR_TYPE }, + { "songvideourl", LISTITEM_SONG_VIDEO_URL }, }; +// clang-format on /// \page modules__infolabels_boolean_conditions /// \subsection modules__infolabels_boolean_conditions_Visualisation Visualisation diff --git a/xbmc/addons/Scraper.cpp b/xbmc/addons/Scraper.cpp index 30c22473af..ad7b251052 100644 --- a/xbmc/addons/Scraper.cpp +++ b/xbmc/addons/Scraper.cpp @@ -816,6 +816,23 @@ void DetailsFromFileItem<CArtist>(const CFileItem &item, CArtist &artist) artist.discography.emplace_back(discoAlbum); } + const int numvideolinks = item.GetProperty("artist.videolinks").asInteger32(); + if (numvideolinks > 0) + { + artist.videolinks.reserve(numvideolinks); + for (int i = 1; i <= numvideolinks; ++i) + { + std::stringstream prefix; + prefix << "artist.videolink" << i; + ArtistVideoLinks videoLink; + videoLink.title = FromString(item, prefix.str() + ".title"); + videoLink.mbTrackID = FromString(item, prefix.str() + ".mbtrackid"); + videoLink.videoURL = FromString(item, prefix.str() + ".url"); + videoLink.thumbURL = FromString(item, prefix.str() + ".thumb"); + artist.videolinks.emplace_back(std::move(videoLink)); + } + } + int nThumbs = item.GetProperty("artist.thumbs").asInteger32(); ParseThumbs(artist.thumbURL, item, nThumbs, "artist.thumb"); diff --git a/xbmc/cores/AudioEngine/Sinks/pipewire/PipewireGlobal.h b/xbmc/cores/AudioEngine/Sinks/pipewire/PipewireGlobal.h index 7b1021ae38..67f40c7220 100644 --- a/xbmc/cores/AudioEngine/Sinks/pipewire/PipewireGlobal.h +++ b/xbmc/cores/AudioEngine/Sinks/pipewire/PipewireGlobal.h @@ -29,21 +29,21 @@ public: CPipewireGlobal() = default; ~CPipewireGlobal(); - CPipewireGlobal& SetName(std::string_view name) + CPipewireGlobal& SetName(const std::string& name) { m_name = name; return *this; } - std::string_view GetName() const { return m_name; } + std::string GetName() const { return m_name; } - CPipewireGlobal& SetDescription(std::string_view description) + CPipewireGlobal& SetDescription(const std::string& description) { m_description = description; return *this; } - std::string_view GetDescription() const { return m_description; } + std::string GetDescription() const { return m_description; } CPipewireGlobal& SetID(uint32_t id) { @@ -61,13 +61,13 @@ public: uint32_t GetPermissions() const { return m_permissions; } - CPipewireGlobal& SetType(std::string_view type) + CPipewireGlobal& SetType(const std::string& type) { m_type = type; return *this; } - std::string_view GetType() const { return m_type; } + std::string GetType() const { return m_type; } CPipewireGlobal& SetVersion(uint32_t version) { @@ -95,11 +95,11 @@ public: CPipewireNode& GetNode() const { return *m_node; } private: - std::string_view m_name; - std::string_view m_description; + std::string m_name; + std::string m_description; uint32_t m_id; uint32_t m_permissions; - std::string_view m_type; + std::string m_type; uint32_t m_version; std::unique_ptr<pw_properties, PipewirePropertiesDeleter> m_properties; std::unique_ptr<CPipewireNode> m_node; diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp index 72419823d8..c4590feca7 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp +++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp @@ -1871,7 +1871,10 @@ void CVideoPlayer::HandlePlaySpeed() CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(21454), g_localizeStrings.Get(21455)); SetCaching(CACHESTATE_INIT); } - if (cache.level >= 1.0) + // Note: Previously used cache.level >= 1 would keep video stalled + // event after cache was full + // Talk link: https://github.com/xbmc/xbmc/pull/23760 + if (cache.time > 8.0) SetCaching(CACHESTATE_INIT); } else diff --git a/xbmc/guilib/guiinfo/GUIInfoLabels.h b/xbmc/guilib/guiinfo/GUIInfoLabels.h index 5d186bc2ef..dfb5b7f422 100644 --- a/xbmc/guilib/guiinfo/GUIInfoLabels.h +++ b/xbmc/guilib/guiinfo/GUIInfoLabels.h @@ -962,6 +962,7 @@ #define LISTITEM_ALBUMSTATUS (LISTITEM_START + 206) #define LISTITEM_ISAUTOUPDATEABLE (LISTITEM_START + 207) #define LISTITEM_VIDEO_HDR_TYPE (LISTITEM_START + 208) +#define LISTITEM_SONG_VIDEO_URL (LISTITEM_START + 209) #define LISTITEM_END (LISTITEM_START + 2500) diff --git a/xbmc/guilib/guiinfo/MusicGUIInfo.cpp b/xbmc/guilib/guiinfo/MusicGUIInfo.cpp index f58a9ae3c4..ca79c2c8de 100644 --- a/xbmc/guilib/guiinfo/MusicGUIInfo.cpp +++ b/xbmc/guilib/guiinfo/MusicGUIInfo.cpp @@ -403,6 +403,9 @@ bool CMusicGUIInfo::GetLabel(std::string& value, const CFileItem *item, int cont return true; } break; + case LISTITEM_SONG_VIDEO_URL: + value = tag->GetSongVideoURL(); + return true; } } 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/interfaces/json-rpc/AudioLibrary.cpp b/xbmc/interfaces/json-rpc/AudioLibrary.cpp index 3521a3a8ae..813c4c85c4 100644 --- a/xbmc/interfaces/json-rpc/AudioLibrary.cpp +++ b/xbmc/interfaces/json-rpc/AudioLibrary.cpp @@ -991,6 +991,8 @@ JSONRPC_STATUS CAudioLibrary::SetSongDetails(const std::string &method, ITranspo song.strOrigReleaseDate = parameterObject["originaldate"].asString(); if (ParameterNotNull(parameterObject, "albumreleasedate")) song.strReleaseDate = parameterObject["albumreleasedate"].asString(); + if (ParameterNotNull(parameterObject, "songvideourl")) + song.songVideoURL = parameterObject["songvideourl"].asString(); // Update existing art. Any existing artwork that isn't specified in this request stays as is. // If the value is null then the existing art with that type is removed. diff --git a/xbmc/interfaces/json-rpc/schema/methods.json b/xbmc/interfaces/json-rpc/schema/methods.json index 4d396cf6ba..c33e23ea31 100644 --- a/xbmc/interfaces/json-rpc/schema/methods.json +++ b/xbmc/interfaces/json-rpc/schema/methods.json @@ -1220,7 +1220,8 @@ { "name": "disctitle", "$ref": "Optional.String" }, { "name": "releasedate", "$ref": "Optional.String" }, { "name": "originaldate", "$ref": "Optional.String" }, - { "name": "bpm", "$ref": "Optional.Integer" } + { "name": "bpm", "$ref": "Optional.Integer" }, + { "name": "songvideourl", "$ref": "Optional.String" } ], "returns": "string" }, diff --git a/xbmc/interfaces/json-rpc/schema/types.json b/xbmc/interfaces/json-rpc/schema/types.json index 86e8b22961..7310ddf55b 100644 --- a/xbmc/interfaces/json-rpc/schema/types.json +++ b/xbmc/interfaces/json-rpc/schema/types.json @@ -545,7 +545,8 @@ "votes", "userrating", "mood", "contributors", "displaycomposer", "displayconductor", "displayorchestra", "displaylyricist", "sortartist", "art", "sourceid", "disctitle", "releasedate", "originaldate", - "bpm", "samplerate", "bitrate", "channels", "datemodified", "datenew" ] + "bpm", "samplerate", "bitrate", "channels", "datemodified", "datenew", + "songvideourl" ] } }, "Audio.Album.ReleaseType": { @@ -692,7 +693,8 @@ "bpm": { "type": "Integer" }, "samplerate": { "type": "Integer" }, "bitrate": { "type": "Integer"}, - "channels": { "type": "Integer"} + "channels": { "type": "Integer"}, + "songvideourl": { "type": "string" } } }, "Audio.Property.Name": { @@ -1572,7 +1574,8 @@ "samplerate": { "type": "integer" }, "channels": { "type": "integer"}, "albumstatus": { "type": "string" }, - "customproperties": { "$ref": "Item.CustomProperties" } + "customproperties": { "$ref": "Item.CustomProperties" }, + "songvideourl": { "type": "string" } } }, "List.Fields.All": { @@ -1597,7 +1600,7 @@ "musicbrainzreleasegroupid", "mediapath", "dynpath", "isboxset", "totaldiscs", "disctitle", "releasedate", "originaldate", "bpm", "bitrate", "samplerate", "channels", "albumstatus", "datemodified", "datenew", "customproperties", - "albumduration"] + "albumduration", "songvideourl"] } }, "List.Item.All": { @@ -1631,7 +1634,7 @@ "specialsortseason", "specialsortepisode", "sortartist", "musicbrainzreleasegroupid", "isboxset", "totaldiscs", "disctitle", "releasedate", "originaldate", "bpm", "bitrate", "samplerate", "channels", "datemodified", "datenew", "customproperties", - "albumduration", "userrating"] + "albumduration", "userrating", "songvideourl" ] } }, "List.Item.File": { diff --git a/xbmc/interfaces/json-rpc/schema/version.txt b/xbmc/interfaces/json-rpc/schema/version.txt index 3f74ab3e4c..998f113d61 100644 --- a/xbmc/interfaces/json-rpc/schema/version.txt +++ b/xbmc/interfaces/json-rpc/schema/version.txt @@ -1 +1 @@ -JSONRPC_VERSION 13.2.1 +JSONRPC_VERSION 13.3.0 diff --git a/xbmc/music/Artist.cpp b/xbmc/music/Artist.cpp index 786f7a737b..c5626c58eb 100644 --- a/xbmc/music/Artist.cpp +++ b/xbmc/music/Artist.cpp @@ -62,6 +62,7 @@ void CArtist::MergeScrapedArtist(const CArtist& source, bool override /* = true art = source.art; discography = source.discography; + videolinks = source.videolinks; } @@ -133,6 +134,24 @@ bool CArtist::Load(const TiXmlElement *artist, bool append, bool prioritise) node = node->NextSiblingElement("album"); } + //song video links + const TiXmlElement* songurls = artist->FirstChildElement("videourl"); + if (songurls) + videolinks.clear(); + while (songurls) + { + if (songurls->FirstChild()) + { + ArtistVideoLinks videoLink; + XMLUtils::GetString(songurls, "title", videoLink.title); + XMLUtils::GetString(songurls, "musicbrainztrackid", videoLink.mbTrackID); + XMLUtils::GetString(songurls, "url", videoLink.videoURL); + XMLUtils::GetString(songurls, "thumburl", videoLink.thumbURL); + videolinks.emplace_back(std::move(videoLink)); + } + songurls = songurls->NextSiblingElement("videourl"); + } + // Support old style <fanart></fanart> for backwards compatibility of old nfo files and scrapers const TiXmlElement *fanart2 = artist->FirstChildElement("fanart"); if (fanart2) @@ -218,6 +237,16 @@ bool CArtist::Save(TiXmlNode *node, const std::string &tag, const std::string& s XMLUtils::SetString(node, "year", it.strYear); XMLUtils::SetString(node, "musicbrainzreleasegroupid", it.strReleaseGroupMBID); } + // song video links + for (const auto& it : videolinks) + { + TiXmlElement videolinkElement("videourl"); + TiXmlNode* node = artist->InsertEndChild(videolinkElement); + XMLUtils::SetString(node, "title", it.title); + XMLUtils::SetString(node, "musicbrainztrackid", it.mbTrackID); + XMLUtils::SetString(node, "url", it.videoURL); + XMLUtils::SetString(node, "thumburl", it.thumbURL); + } return true; } diff --git a/xbmc/music/Artist.h b/xbmc/music/Artist.h index 2ec77a8254..8791288f26 100644 --- a/xbmc/music/Artist.h +++ b/xbmc/music/Artist.h @@ -29,6 +29,14 @@ public: std::string strReleaseGroupMBID; }; +struct ArtistVideoLinks +{ + std::string title; + std::string mbTrackID; + std::string videoURL; + std::string thumbURL; +}; + class CArtist { public: @@ -76,6 +84,7 @@ public: dateNew.Reset(); bScrapedMBID = false; strLastScraped.clear(); + videolinks.clear(); } /*! \brief Load artist information from an XML file. @@ -117,6 +126,7 @@ public: CDateTime dateNew; // Time db record created bool bScrapedMBID = false; std::string strLastScraped; + std::vector<ArtistVideoLinks> videolinks; }; class CArtistCredit diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp index 69819a98e4..dd54a6379a 100644 --- a/xbmc/music/MusicDatabase.cpp +++ b/xbmc/music/MusicDatabase.cpp @@ -203,6 +203,7 @@ void CMusicDatabase::CreateTables() " comment text, mood text, iBPM INTEGER NOT NULL DEFAULT 0, " " iBitRate INTEGER NOT NULL DEFAULT 0, " " iSampleRate INTEGER NOT NULL DEFAULT 0, iChannels INTEGER NOT NULL DEFAULT 0, " + " strVideoURL TEXT, " " strReplayGain text, " " dateAdded TEXT, dateNew TEXT, dateModified TEXT)"); CLog::Log(LOGINFO, "create song_artist table"); @@ -452,6 +453,7 @@ void CMusicDatabase::CreateViews() " iBitRate, " " iSampleRate, " " iChannels, " + " song.strVideoURL as strVideoURL, " " album.iAlbumDuration AS iAlbumDuration, " " album.iDiscTotal as iDiscTotal, " " song.dateAdded as dateAdded, " @@ -769,6 +771,7 @@ bool CMusicDatabase::AddAlbum(CAlbum& album, int idSource) song->userrating, // song->votes, // song->iBPM, song->iBitRate, song->iSampleRate, song->iChannels, // + song->songVideoURL, // song->replayGain); // Song must have at least one artist so set artist to [Missing] @@ -1019,6 +1022,7 @@ int CMusicDatabase::AddSong(const int idSong, int iBitRate, int iSampleRate, int iChannels, + const std::string& songVideoURL, const ReplayGain& replayGain) { int idNew = -1; @@ -1146,7 +1150,7 @@ int CMusicDatabase::AddSong(const int idSong, dtLastPlayed, // rating, userrating, votes, // replayGain, // - iBPM, iBitRate, iSampleRate, iChannels); + iBPM, iBitRate, iSampleRate, iChannels, songVideoURL); } if (!strThumb.empty()) SetArtForItem(idNew, MediaTypeSong, "thumb", strThumb); @@ -1238,7 +1242,8 @@ bool CMusicDatabase::UpdateSong(CSong& song, bool bArtists /*= true*/, bool bArt song.lastPlayed, // song.rating, song.userrating, song.votes, // song.replayGain, // - song.iBPM, song.iBitRate, song.iSampleRate, song.iChannels); + song.iBPM, song.iBitRate, song.iSampleRate, song.iChannels, // + song.songVideoURL); if (result < 0) return false; @@ -1297,7 +1302,8 @@ int CMusicDatabase::UpdateSong(int idSong, int iBPM, int iBitRate, int iSampleRate, - int iChannels) + int iChannels, + const std::string& songVideoURL) { if (idSong < 0) return -1; @@ -1319,7 +1325,7 @@ int CMusicDatabase::UpdateSong(int idSong, " strTitle = '%s', iTrack = %i, iDuration = %i, " "strReleaseDate = '%s', strOrigReleaseDate = '%s', strDiscSubtitle = '%s', " "strFileName = '%s', iBPM = %i, iBitrate = %i, iSampleRate = %i, iChannels = %i, " - "dateAdded = '%s'", + "dateAdded = '%s', strVideoURL = '%s'", idPath, artistDisp.c_str(), StringUtils::Join( genres, @@ -1327,7 +1333,7 @@ int CMusicDatabase::UpdateSong(int idSong, .c_str(), strTitle.c_str(), iTrack, iDuration, strRelease.c_str(), strOriginal.c_str(), strDiscSubtitle.c_str(), strFileName.c_str(), iBPM, iBitRate, iSampleRate, iChannels, - strDateMedia.c_str()); + strDateMedia.c_str(), songVideoURL.c_str()); if (strMusicBrainzTrackID.empty()) strSQL += PrepareSQL(", strMusicBrainzTrackID = NULL"); else @@ -1756,6 +1762,11 @@ bool CMusicDatabase::UpdateArtist(const CArtist& artist) AddArtistDiscography(artist.idArtist, disc); } + if (!DeleteArtistVideoLinks(artist.idArtist)) + CLog::Log(LOGERROR, "MusicDatabase: Error deleting ArtistVideoLinks"); + + AddArtistVideoLinks(artist); + // Set current artwork (held in art table) if (!artist.art.empty()) SetArtForItem(artist.idArtist, MediaTypeArtist, artist.art); @@ -2037,6 +2048,8 @@ bool CMusicDatabase::GetArtist(int idArtist, CArtist& artist, bool fetchAll /* = return false; if (nullptr == m_pDS) return false; + if (nullptr == m_pDS2) + return false; if (idArtist == -1) return false; // not in the database @@ -2057,7 +2070,7 @@ bool CMusicDatabase::GetArtist(int idArtist, CArtist& artist, bool fetchAll /* = m_pDS->close(); return false; } - + std::string debugSQL = strSQL + " - "; int discographyOffset = artist_enumCount; artist.discography.clear(); @@ -2077,12 +2090,36 @@ bool CMusicDatabase::GetArtist(int idArtist, CArtist& artist, bool fetchAll /* = } m_pDS->close(); // cleanup recordset data + artist.videolinks.clear(); + if (fetchAll) + { + strSQL = PrepareSQL("SELECT idSong, strTitle, strMusicBrainzTrackID, strVideoURL, url " + "FROM song JOIN album_artist ON song.idAlbum = album_artist.idAlbum " + "LEFT JOIN art ON art.media_id = song.idSong AND art.type = 'videothumb' " + "WHERE album_artist.idArtist = %i AND " + "song.strVideoURL is not NULL GROUP by song.strVideoURL ORDER BY idSong", + idArtist); + debugSQL += strSQL; + m_pDS->query(strSQL); + while (!m_pDS->eof()) + { + const dbiplus::sql_record* const record = m_pDS->get_sql_record(); + ArtistVideoLinks videoLink; + videoLink.title = record->at(1).get_asString(); + videoLink.mbTrackID = record->at(2).get_asString(); + videoLink.videoURL = record->at(3).get_asString(); + videoLink.thumbURL = record->at(4).get_asString(); + + artist.videolinks.emplace_back(std::move(videoLink)); + m_pDS->next(); + } + m_pDS->close(); + } + auto end = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); - CLog::Log(LOGDEBUG, LOGDATABASE, "{0}({1}) - took {2} ms", __FUNCTION__, strSQL, - duration.count()); - + CLog::LogF(LOGDEBUG, "{} - took {} ms", debugSQL, duration.count()); return true; } catch (...) @@ -2180,6 +2217,92 @@ bool CMusicDatabase::ClearArtistLastScrapedTime(int idArtist) return ExecuteQuery(strSQL); } +bool CMusicDatabase::AddArtistVideoLinks(const CArtist& artist) +{ + auto start = std::chrono::steady_clock::now(); + std::string dbSong; + + try + { + if (nullptr == m_pDB || nullptr == m_pDS || nullptr == m_pDS2) + return false; + + for (const auto& videoURL : artist.videolinks) + { + dbSong = videoURL.title; + std::string strSQL = PrepareSQL( + "SELECT idSong, strTitle FROM song WHERE strMusicBrainzTrackID = '%s' OR (EXISTS " + "(SELECT 1 FROM album_artist WHERE album_artist.idAlbum = song.idAlbum AND " + "album_artist.idArtist = '%i' AND song.strTitle LIKE '%%%s%%'))", + videoURL.mbTrackID.c_str(), artist.idArtist, videoURL.title.c_str()); + + if (!m_pDS->query(strSQL)) + return false; + if (m_pDS->num_rows() == 0) + continue; + + while (!m_pDS->eof()) + { + const int songId = m_pDS->fv(0).get_asInt(); + std::string strSQL2 = PrepareSQL("UPDATE song SET strVideoURL='%s' WHERE idSong = %i", + videoURL.videoURL.c_str(), songId); + CLog::Log(LOGDEBUG, "Adding videolink for song {} with id {}", dbSong.c_str(), songId); + m_pDS2->exec(strSQL2); + + if (!videoURL.thumbURL.empty()) + { // already have a videothumb for this song ? + strSQL2 = PrepareSQL("SELECT art_id FROM art " + "WHERE media_id=%i AND media_type='%s' AND type='videothumb'", + songId, MediaTypeSong); + m_pDS2->query(strSQL2); + if (!m_pDS2->eof()) + { // update existing thumb + const int artId = m_pDS2->fv(0).get_asInt(); + m_pDS2->close(); + strSQL2 = PrepareSQL("UPDATE art SET url='%s' where art_id=%d", + videoURL.thumbURL.c_str(), artId); + m_pDS2->exec(strSQL2); + } + else + { // insert new thumb + m_pDS2->close(); + strSQL2 = PrepareSQL("INSERT INTO art(media_id, media_type, type, url) " + "VALUES (%d, '%s', '%s', '%s')", + songId, MediaTypeSong, "videothumb", videoURL.thumbURL.c_str()); + m_pDS2->exec(strSQL2); + } + m_pDS2->close(); + } + m_pDS->next(); + } + m_pDS->close(); + } + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); + CLog::LogF(LOGDEBUG, "Time to store videolinks {}ms ", duration.count()); + return true; + } + catch (...) + { + CLog::Log(LOGERROR, "MusicDatabase: Unable to add videolink for song ({})", dbSong.c_str()); + return false; + } +} + +bool CMusicDatabase::DeleteArtistVideoLinks(const int idArtist) +{ + std::string strSQL = PrepareSQL("UPDATE song SET strVideoURL = NULL WHERE idAlbum IN " + "(SELECT idAlbum FROM album_artist WHERE idArtist = %i)", + idArtist); + if (!ExecuteQuery(strSQL)) + return false; + strSQL = PrepareSQL( + "DELETE FROM art WHERE art.type = 'videothumb' AND art.media_id IN (SELECT idSong FROM song " + "JOIN album_artist ON song.idAlbum = album_artist.idAlbum WHERE album_artist.idArtist = %i)", + idArtist); + return ExecuteQuery(strSQL); +} + int CMusicDatabase::AddArtistDiscography(int idArtist, const CDiscoAlbum& discoAlbum) { std::string strSQL = PrepareSQL("INSERT INTO discography " @@ -2994,6 +3117,7 @@ CSong CMusicDatabase::GetSongFromDataset(const dbiplus::sql_record* const record song.iBitRate = record->at(offset + song_iBitRate).get_asInt(); song.iSampleRate = record->at(offset + song_iSampleRate).get_asInt(); song.iChannels = record->at(offset + song_iChannels).get_asInt(); + song.songVideoURL = record->at(offset + song_songVideoURL).get_asString(); return song; } @@ -3056,6 +3180,7 @@ void CMusicDatabase::GetFileItemFromDataset(const dbiplus::sql_record* const rec replaygain.Set(record->at(song_strReplayGain).get_asString()); item->GetMusicInfoTag()->SetReplayGain(replaygain); item->GetMusicInfoTag()->SetTotalDiscs(record->at(song_iDiscTotal).get_asInt()); + item->GetMusicInfoTag()->SetSongVideoURL(record->at(song_songVideoURL).get_asString()); item->GetMusicInfoTag()->SetLoaded(true); // Get filename with full path @@ -7578,6 +7703,7 @@ static const translateJSONField JSONtoDBSong[] = { { "bitrate", "integer", true, "iBitRate", "" }, { "samplerate", "integer", true, "iSampleRate", "" }, { "channels", "integer", true, "iChannels", "" }, + { "songvideourl", "string", true, "strVideoURL", "" }, // JOIN fields (multivalue), same order as _JoinToSongFields { "albumartistid", "array", false, "idAlbumArtist", "album_artist.idArtist AS idAlbumArtist" }, @@ -9288,6 +9414,10 @@ void CMusicDatabase::UpdateTables(int version) m_pDS->exec("DROP TABLE artist"); m_pDS->exec("ALTER TABLE artist_new RENAME TO artist"); } + + if (version < 83) + m_pDS->exec("ALTER TABLE song ADD strVideoURL TEXT"); + // Set the version of tag scanning required. // Not every schema change requires the tags to be rescanned, set to the highest schema version // that needs this. Forced rescanning (of music files that have not changed since they were @@ -9308,7 +9438,7 @@ void CMusicDatabase::UpdateTables(int version) int CMusicDatabase::GetSchemaVersion() const { - return 82; + return 83; } int CMusicDatabase::GetMusicNeedsTagScan() diff --git a/xbmc/music/MusicDatabase.h b/xbmc/music/MusicDatabase.h index 8544eb297d..791ff3d9cd 100644 --- a/xbmc/music/MusicDatabase.h +++ b/xbmc/music/MusicDatabase.h @@ -140,6 +140,7 @@ public: \param rating [in] a rating for the song \param userrating [in] a userrating (my rating) for the song \param votes [in] a vote counter for the song rating + \param songVideoURL [in] url to video of the song \param replayGain [in] album and track replaygain and peak values \return the id of the song */ @@ -171,6 +172,7 @@ public: int iBitRate, int iSampleRate, int iChannels, + const std::string& songVideoURL, const ReplayGain& replayGain); bool GetSong(int idSong, CSong& song); @@ -210,6 +212,7 @@ public: \param iBitRate [in] the bitrate of the song file \param iSampleRate [in] the sample rate of the song file \param iChannels [in] the number of audio channels in the song file + \param songVideoURL [in] url link to a video of the song \return the id of the song */ int UpdateSong(int idSong, @@ -238,7 +241,8 @@ public: int iBPM, int iBitRate, int iSampleRate, - int iChannels); + int iChannels, + const std::string& songVideoURL); //// Misc Song bool GetSongByFileName(const std::string& strFileName, CSong& song, int64_t startOffset = 0); @@ -405,6 +409,8 @@ public: int AddArtistDiscography(int idArtist, const CDiscoAlbum& discoAlbum); bool DeleteArtistDiscography(int idArtist); bool GetArtistDiscography(int idArtist, CFileItemList& items); + bool AddArtistVideoLinks(const CArtist& artist); + bool DeleteArtistVideoLinks(const int idArtist); std::string GetArtistById(int id); int GetArtistByName(const std::string& strArtist); @@ -1017,6 +1023,7 @@ private: song_iBitRate, song_iSampleRate, song_iChannels, + song_songVideoURL, song_iAlbumDuration, song_iDiscTotal, song_dateAdded, diff --git a/xbmc/music/Song.cpp b/xbmc/music/Song.cpp index 165889ca92..93b2156d7b 100644 --- a/xbmc/music/Song.cpp +++ b/xbmc/music/Song.cpp @@ -75,6 +75,7 @@ CSong::CSong(CFileItem& item) iSampleRate = tag.GetSampleRate(); iBitRate = tag.GetBitRate(); iChannels = tag.GetNoOfChannels(); + songVideoURL = tag.GetSongVideoURL(); } CSong::CSong() @@ -239,6 +240,7 @@ void CSong::Serialize(CVariant& value) const value["bitrate"] = iBitRate; value["samplerate"] = iSampleRate; value["channels"] = iChannels; + value["songvideourl"] = songVideoURL; } void CSong::Clear() @@ -279,6 +281,7 @@ void CSong::Clear() iBitRate = 0; iSampleRate = 0; iChannels = 0; + songVideoURL.clear(); replayGain = ReplayGain(); } diff --git a/xbmc/music/Song.h b/xbmc/music/Song.h index 3fc127a60f..737ba46eed 100644 --- a/xbmc/music/Song.h +++ b/xbmc/music/Song.h @@ -194,6 +194,7 @@ public: int iChannels; std::string strRecordLabel; // Record label from tag for album processing by CMusicInfoScanner::FileItemsToAlbums std::string strAlbumType; // (Musicbrainz release type) album type from tag for album processing by CMusicInfoScanner::FileItemsToAlbums + std::string songVideoURL; // url to song video ReplayGain replayGain; private: diff --git a/xbmc/music/tags/MusicInfoTag.cpp b/xbmc/music/tags/MusicInfoTag.cpp index 62548bf5d5..50c7ae773b 100644 --- a/xbmc/music/tags/MusicInfoTag.cpp +++ b/xbmc/music/tags/MusicInfoTag.cpp @@ -323,6 +323,11 @@ const std::string& CMusicInfoTag::GetStationArt() const return m_stationArt; } +const std::string& CMusicInfoTag::GetSongVideoURL() const +{ + return m_songVideoURL; +} + void CMusicInfoTag::SetURL(const std::string& strURL) { m_strURL = strURL; @@ -774,6 +779,11 @@ void CMusicInfoTag::SetStationArt(const std::string& strStationArt) m_stationArt = strStationArt; } +void CMusicInfoTag::SetSongVideoURL(const std::string& songVideoURL) +{ + m_songVideoURL = songVideoURL; +} + void CMusicInfoTag::SetArtist(const CArtist& artist) { SetArtist(artist.strArtist); @@ -882,6 +892,7 @@ void CMusicInfoTag::SetSong(const CSong& song) SetBitRate(song.iBitRate); SetSampleRate(song.iSampleRate); SetNoOfChannels(song.iChannels); + SetSongVideoURL(song.songVideoURL); if (song.replayGain.Get(ReplayGain::TRACK).Valid()) m_replayGain.Set(ReplayGain::TRACK, song.replayGain.Get(ReplayGain::TRACK)); @@ -970,6 +981,7 @@ void CMusicInfoTag::Serialize(CVariant& value) const value["bitrate"] = m_bitrate; value["samplerate"] = m_samplerate; value["channels"] = m_channels; + value["songvideourl"] = m_songVideoURL; } void CMusicInfoTag::ToSortable(SortItem& sortable, Field field) const @@ -1071,6 +1083,7 @@ void CMusicInfoTag::Archive(CArchive& ar) ar << m_samplerate; ar << m_bitrate; ar << m_channels; + ar << m_songVideoURL; } else { @@ -1138,6 +1151,7 @@ void CMusicInfoTag::Archive(CArchive& ar) ar >> m_samplerate; ar >> m_bitrate; ar >> m_channels; + ar >> m_songVideoURL; } } @@ -1193,6 +1207,7 @@ void CMusicInfoTag::Clear() m_channels = 0; m_stationName.clear(); m_stationArt.clear(); + m_songVideoURL.clear(); } void CMusicInfoTag::AppendArtist(const std::string &artist) diff --git a/xbmc/music/tags/MusicInfoTag.h b/xbmc/music/tags/MusicInfoTag.h index 3c1b994425..0b264a9301 100644 --- a/xbmc/music/tags/MusicInfoTag.h +++ b/xbmc/music/tags/MusicInfoTag.h @@ -85,6 +85,7 @@ public: const std::string& GetAlbumReleaseStatus() const; const std::string& GetStationName() const; const std::string& GetStationArt() const; + const std::string& GetSongVideoURL() const; const EmbeddedArtInfo &GetCoverArtInfo() const; const ReplayGain& GetReplayGain() const; CAlbum::ReleaseType GetAlbumReleaseType() const; @@ -157,6 +158,7 @@ public: void SetAlbumReleaseStatus(const std::string& strReleaseStatus); void SetStationName(const std::string& strStationName); // name of online radio station void SetStationArt(const std::string& strStationArt); + void SetSongVideoURL(const std::string& songVideoURL); // link to video of song /*! \brief Append a unique artist to the artist list Checks if we have this artist already added, and if not adds it to the songs artist list. @@ -255,6 +257,7 @@ protected: int m_bitrate; std::string m_stationName; std::string m_stationArt; // Used to fetch thumb URL for Shoutcasts + std::string m_songVideoURL; // link to a video for a song EmbeddedArtInfo m_coverArt; ///< art information 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/rendering/dx/DeviceResources.cpp b/xbmc/rendering/dx/DeviceResources.cpp index 8cfe5cf62c..103809d591 100644 --- a/xbmc/rendering/dx/DeviceResources.cpp +++ b/xbmc/rendering/dx/DeviceResources.cpp @@ -729,7 +729,6 @@ void DX::DeviceResources::ResizeBuffers() ComPtr<IDXGIDevice1> dxgiDevice; hr = m_d3dDevice.As(&dxgiDevice); CHECK_ERR(); dxgiDevice->SetMaximumFrameLatency(1); - m_usedSwapChain = false; if (m_IsHDROutput) SetHdrColorSpace(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020); @@ -960,7 +959,6 @@ void DX::DeviceResources::HandleDeviceLost(bool removed) bool DX::DeviceResources::Begin() { HRESULT hr = m_swapChain->Present(0, DXGI_PRESENT_TEST); - m_usedSwapChain = true; // If the device was removed either by a disconnection or a driver upgrade, we // must recreate all device resources. @@ -992,7 +990,6 @@ void DX::DeviceResources::Present() // frames that will never be displayed to the screen. DXGI_PRESENT_PARAMETERS parameters = {}; HRESULT hr = m_swapChain->Present1(1, 0, ¶meters); - m_usedSwapChain = true; // If the device was removed either by a disconnection or a driver upgrade, we // must recreate all device resources. @@ -1311,23 +1308,6 @@ void DX::DeviceResources::SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpac if (SUCCEEDED(m_swapChain.As(&swapChain3))) { - // Set the color space on a new swap chain - not mandated by MS documentation but needed - // at least for some AMD on Windows 10, at least up to driver 31.0.21001.45002 - // Applying to AMD only because it breaks refresh rate switching in Windows 11 for Intel and - // nVidia and they don't need the workaround. - if (m_usedSwapChain && - m_IsTransferPQ != (colorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)) - { - if (GetAdapterDesc().VendorId == PCIV_AMD) - { - // Temporary release, can't hold references during swap chain re-creation - swapChain3 = nullptr; - DestroySwapChain(); - CreateWindowSizeDependentResources(); - m_swapChain.As(&swapChain3); - } - } - if (SUCCEEDED(swapChain3->SetColorSpace1(colorSpace))) { m_IsTransferPQ = (colorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020); diff --git a/xbmc/rendering/dx/DeviceResources.h b/xbmc/rendering/dx/DeviceResources.h index 01fa76a659..8d325ee6dc 100644 --- a/xbmc/rendering/dx/DeviceResources.h +++ b/xbmc/rendering/dx/DeviceResources.h @@ -188,7 +188,6 @@ namespace DX bool m_NV12SharedTexturesSupport{false}; bool m_DXVA2SharedDecoderSurfaces{false}; bool m_DXVASuperResolutionSupport{false}; - bool m_usedSwapChain{false}; bool m_DXVA2UseFence{false}; }; } 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/tags/VideoTagExtractionHelper.cpp b/xbmc/video/tags/VideoTagExtractionHelper.cpp index 5ce567aed9..b331305fc4 100644 --- a/xbmc/video/tags/VideoTagExtractionHelper.cpp +++ b/xbmc/video/tags/VideoTagExtractionHelper.cpp @@ -21,10 +21,9 @@ 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"); + URIUtils::HasExtension(item.GetDynPath(), ".mkv|.mp4|.avi|.m4v"); } std::string CVideoTagExtractionHelper::ExtractEmbeddedArtFor(const CFileItem& item, @@ -36,10 +35,7 @@ std::string CVideoTagExtractionHelper::ExtractEmbeddedArtFor(const CFileItem& it for (const auto& it : tag.m_coverArt) { if (it.m_type == artType) - { - return CTextureUtils::GetWrappedImageURL(item.GetVideoInfoTag()->m_strFileNameAndPath, - "video_" + artType); - } + return CTextureUtils::GetWrappedImageURL(item.GetDynPath(), "video_" + artType); } return {}; } 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> |