aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/scripts/windows/ArchSetup.cmake2
-rw-r--r--cmake/scripts/windowsstore/ArchSetup.cmake2
-rw-r--r--docs/README.Windows.md3
-rw-r--r--xbmc/HDRStatus.h1
-rw-r--r--xbmc/SeekHandler.cpp4
-rw-r--r--xbmc/application/ApplicationPlayer.cpp4
-rw-r--r--xbmc/application/ApplicationPlayer.h2
-rw-r--r--xbmc/cores/Direction.h18
-rw-r--r--xbmc/cores/IPlayer.h3
-rw-r--r--xbmc/cores/VideoPlayer/Edl.cpp105
-rw-r--r--xbmc/cores/VideoPlayer/Edl.h48
-rw-r--r--xbmc/cores/VideoPlayer/VideoPlayer.cpp17
-rw-r--r--xbmc/cores/VideoPlayer/VideoPlayer.h2
-rw-r--r--xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp21
-rw-r--r--xbmc/platform/win10/CMakeLists.txt4
-rw-r--r--xbmc/platform/win32/CMakeLists.txt4
-rw-r--r--xbmc/platform/win32/WIN32Util.cpp75
-rw-r--r--xbmc/platform/win32/WIN32Util.h3
-rw-r--r--xbmc/platform/win32/WinRtUtil.cpp202
-rw-r--r--xbmc/platform/win32/WinRtUtil.h22
-rw-r--r--xbmc/rendering/dx/DeviceResources.h1
-rw-r--r--xbmc/rendering/dx/DirectXHelper.h16
22 files changed, 386 insertions, 173 deletions
diff --git a/cmake/scripts/windows/ArchSetup.cmake b/cmake/scripts/windows/ArchSetup.cmake
index b19789d5bb..7116196207 100644
--- a/cmake/scripts/windows/ArchSetup.cmake
+++ b/cmake/scripts/windows/ArchSetup.cmake
@@ -1,5 +1,5 @@
# Minimum SDK version we support
-set(VS_MINIMUM_SDK_VERSION 10.0.18362.0)
+set(VS_MINIMUM_SDK_VERSION 10.0.22621.0)
if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION VERSION_LESS VS_MINIMUM_SDK_VERSION)
message(FATAL_ERROR "Detected Windows SDK version is ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}.\n"
diff --git a/cmake/scripts/windowsstore/ArchSetup.cmake b/cmake/scripts/windowsstore/ArchSetup.cmake
index c3e580aa69..a39914cca0 100644
--- a/cmake/scripts/windowsstore/ArchSetup.cmake
+++ b/cmake/scripts/windowsstore/ArchSetup.cmake
@@ -1,5 +1,5 @@
# Minimum SDK version we support
-set(VS_MINIMUM_SDK_VERSION 10.0.18362.0)
+set(VS_MINIMUM_SDK_VERSION 10.0.22621.0)
if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION VERSION_LESS VS_MINIMUM_SDK_VERSION)
message(FATAL_ERROR "Detected Windows SDK version is ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}.\n"
diff --git a/docs/README.Windows.md b/docs/README.Windows.md
index 44ab5ee352..60ece12300 100644
--- a/docs/README.Windows.md
+++ b/docs/README.Windows.md
@@ -1,7 +1,7 @@
![Kodi Logo](resources/banner_slim.png)
# Windows build guide
-This guide has been tested with Windows 10 Pro x64, version 21H2, build 19044.1415. Please read it in full before you proceed to familiarize yourself with the build procedure.
+This guide has been tested with Windows 10 Pro x64, version 22H2, build 19045.4529. Please read it in full before you proceed to familiarize yourself with the build procedure.
## Table of Contents
1. **[Document conventions](#1-document-conventions)**
@@ -83,6 +83,7 @@ Default options are fine.
Start the Visual Studio installer and click **Workloads** select
* Under **Desktop & Mobile** section select
* `Desktop development with C++`
+ * Select the optional element Windows 11 SDK (10.0.22621.0)
* `Universal Windows Platform development` (if compiling for UWP or UWP-ARM)
Click in **Individual components** select
diff --git a/xbmc/HDRStatus.h b/xbmc/HDRStatus.h
index 8fe5aaec53..72613e12cd 100644
--- a/xbmc/HDRStatus.h
+++ b/xbmc/HDRStatus.h
@@ -10,6 +10,7 @@
enum class HDR_STATUS
{
+ HDR_UNKNOWN = -2,
HDR_TOGGLE_FAILED = -1,
HDR_UNSUPPORTED = 0,
HDR_OFF = 1,
diff --git a/xbmc/SeekHandler.cpp b/xbmc/SeekHandler.cpp
index 3e93694b16..7d84926348 100644
--- a/xbmc/SeekHandler.cpp
+++ b/xbmc/SeekHandler.cpp
@@ -311,12 +311,12 @@ bool CSeekHandler::OnAction(const CAction &action)
}
case ACTION_NEXT_SCENE:
{
- appPlayer->SeekScene(true);
+ appPlayer->SeekScene(Direction::FORWARD);
return true;
}
case ACTION_PREV_SCENE:
{
- appPlayer->SeekScene(false);
+ appPlayer->SeekScene(Direction::BACKWARD);
return true;
}
case ACTION_ANALOG_SEEK_FORWARD:
diff --git a/xbmc/application/ApplicationPlayer.cpp b/xbmc/application/ApplicationPlayer.cpp
index 18e78d3c0c..9a59242a85 100644
--- a/xbmc/application/ApplicationPlayer.cpp
+++ b/xbmc/application/ApplicationPlayer.cpp
@@ -327,10 +327,10 @@ bool CApplicationPlayer::CanSeek() const
return (player && player->CanSeek());
}
-bool CApplicationPlayer::SeekScene(bool bPlus)
+bool CApplicationPlayer::SeekScene(Direction seekDirection)
{
std::shared_ptr<IPlayer> player = GetInternal();
- return (player && player->SeekScene(bPlus));
+ return (player && player->SeekScene(seekDirection));
}
void CApplicationPlayer::SeekTime(int64_t iTime)
diff --git a/xbmc/application/ApplicationPlayer.h b/xbmc/application/ApplicationPlayer.h
index d695f66aef..ccee506bd6 100644
--- a/xbmc/application/ApplicationPlayer.h
+++ b/xbmc/application/ApplicationPlayer.h
@@ -144,7 +144,7 @@ public:
void Seek(bool bPlus = true, bool bLargeStep = false, bool bChapterOverride = false);
int SeekChapter(int iChapter);
void SeekPercentage(float fPercent = 0);
- bool SeekScene(bool bPlus = true);
+ bool SeekScene(Direction seekDirection);
void SeekTime(int64_t iTime = 0);
void SeekTimeRelative(int64_t iTime = 0);
void SetAudioStream(int iStream);
diff --git a/xbmc/cores/Direction.h b/xbmc/cores/Direction.h
new file mode 100644
index 0000000000..ffcfe73683
--- /dev/null
+++ b/xbmc/cores/Direction.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2024 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
+
+/*!
+ * @brief Specifies/Abstracts a direction
+*/
+enum class Direction : bool
+{
+ FORWARD, /*!< Forward */
+ BACKWARD /*!< Backward */
+};
diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h
index a782dd72ac..d988d77527 100644
--- a/xbmc/cores/IPlayer.h
+++ b/xbmc/cores/IPlayer.h
@@ -8,6 +8,7 @@
#pragma once
+#include "Direction.h"
#include "IPlayerCallback.h"
#include "Interface/StreamInfo.h"
#include "MenuType.h"
@@ -105,7 +106,7 @@ public:
virtual bool IsPassthrough() const { return false;}
virtual bool CanSeek() const { return true; }
virtual void Seek(bool bPlus = true, bool bLargeStep = false, bool bChapterOverride = false) = 0;
- virtual bool SeekScene(bool bPlus = true) {return false;}
+ virtual bool SeekScene(Direction seekDirection) { return false; }
virtual void SeekPercentage(float fPercent = 0){}
virtual float GetCachePercentage() const { return 0; }
virtual void SetMute(bool bOnOff){}
diff --git a/xbmc/cores/VideoPlayer/Edl.cpp b/xbmc/cores/VideoPlayer/Edl.cpp
index 01c7ed09b1..664358a4f5 100644
--- a/xbmc/cores/VideoPlayer/Edl.cpp
+++ b/xbmc/cores/VideoPlayer/Edl.cpp
@@ -43,56 +43,57 @@ void CEdl::Clear()
m_lastEditTime = -1;
}
-bool CEdl::ReadEditDecisionLists(const CFileItem& fileItem, const float fFramesPerSecond)
+bool CEdl::ReadEditDecisionLists(const CFileItem& fileItem, float fps)
{
- bool bFound = false;
+ bool found = false;
/*
* Only check for edit decision lists if the movie is on the local hard drive, or accessed over a
* network share (even if from a different private network).
*/
- const std::string& strMovie = fileItem.GetDynPath();
- if ((URIUtils::IsHD(strMovie) || URIUtils::IsOnLAN(strMovie, LanCheckMode::ANY_PRIVATE_SUBNET)) &&
- !URIUtils::IsInternetStream(strMovie))
+ const std::string& mediaFilePath = fileItem.GetDynPath();
+ if ((URIUtils::IsHD(mediaFilePath) ||
+ URIUtils::IsOnLAN(mediaFilePath, LanCheckMode::ANY_PRIVATE_SUBNET)) &&
+ !URIUtils::IsInternetStream(mediaFilePath))
{
CLog::Log(LOGDEBUG,
"{} - Checking for edit decision lists (EDL) on local drive or remote share for: {}",
- __FUNCTION__, CURL::GetRedacted(strMovie));
+ __FUNCTION__, CURL::GetRedacted(mediaFilePath));
/*
* Read any available file format until a valid EDL related file is found.
*/
- if (!bFound)
- bFound = ReadVideoReDo(strMovie);
+ if (!found)
+ found = ReadVideoReDo(mediaFilePath);
- if (!bFound)
- bFound = ReadEdl(strMovie, fFramesPerSecond);
+ if (!found)
+ found = ReadEdl(mediaFilePath, fps);
- if (!bFound)
- bFound = ReadComskip(strMovie, fFramesPerSecond);
+ if (!found)
+ found = ReadComskip(mediaFilePath, fps);
- if (!bFound)
- bFound = ReadBeyondTV(strMovie);
+ if (!found)
+ found = ReadBeyondTV(mediaFilePath);
}
else
{
- bFound = ReadPvr(fileItem);
+ found = ReadPvr(fileItem);
}
- if (bFound)
+ if (found)
{
MergeShortCommBreaks();
AddSceneMarkersAtStartAndEndOfEdits();
}
- return bFound;
+ return found;
}
-bool CEdl::ReadEdl(const std::string& strMovie, const float fFramesPerSecond)
+bool CEdl::ReadEdl(const std::string& mediaFilePath, float fps)
{
Clear();
- std::string edlFilename(URIUtils::ReplaceExtension(strMovie, ".edl"));
+ const std::string edlFilename(URIUtils::ReplaceExtension(mediaFilePath, ".edl"));
if (!CFile::Exists(edlFilename))
return false;
@@ -190,10 +191,10 @@ bool CEdl::ReadEdl(const std::string& strMovie, const float fFramesPerSecond)
}
else if (strFields[i][0] == '#') // #12345 format for frame number
{
- if (fFramesPerSecond > 0.0f)
+ if (fps > 0.0f)
{
- editStartEnd[i] = static_cast<int64_t>(std::atol(strFields[i].substr(1).c_str()) /
- fFramesPerSecond * 1000); // frame number to ms
+ editStartEnd[i] = static_cast<int64_t>(std::atol(strFields[i].substr(1).c_str()) / fps *
+ 1000); // frame number to ms
}
else
{
@@ -281,11 +282,11 @@ bool CEdl::ReadEdl(const std::string& strMovie, const float fFramesPerSecond)
}
}
-bool CEdl::ReadComskip(const std::string& strMovie, const float fFramesPerSecond)
+bool CEdl::ReadComskip(const std::string& mediaFilePath, float fps)
{
Clear();
- std::string comskipFilename(URIUtils::ReplaceExtension(strMovie, ".txt"));
+ const std::string comskipFilename(URIUtils::ReplaceExtension(mediaFilePath, ".txt"));
if (!CFile::Exists(comskipFilename))
return false;
@@ -315,9 +316,9 @@ bool CEdl::ReadComskip(const std::string& strMovie, const float fFramesPerSecond
/*
* Not all generated Comskip files have the frame rate information.
*/
- if (fFramesPerSecond > 0.0f)
+ if (fps > 0.0f)
{
- fFrameRate = fFramesPerSecond;
+ fFrameRate = fps;
CLog::Log(LOGWARNING,
"Edl::ReadComskip - Frame rate not in Comskip file. Using detected frames per "
"second: {:.3f}",
@@ -376,7 +377,7 @@ bool CEdl::ReadComskip(const std::string& strMovie, const float fFramesPerSecond
}
}
-bool CEdl::ReadVideoReDo(const std::string& strMovie)
+bool CEdl::ReadVideoReDo(const std::string& mediaFilePath)
{
/*
* VideoReDo file is strange. Tags are XML like, but it isn't an XML file.
@@ -385,7 +386,7 @@ bool CEdl::ReadVideoReDo(const std::string& strMovie)
*/
Clear();
- std::string videoReDoFilename(URIUtils::ReplaceExtension(strMovie, ".Vprj"));
+ const std::string videoReDoFilename(URIUtils::ReplaceExtension(mediaFilePath, ".Vprj"));
if (!CFile::Exists(videoReDoFilename))
return false;
@@ -474,11 +475,12 @@ bool CEdl::ReadVideoReDo(const std::string& strMovie)
}
}
-bool CEdl::ReadBeyondTV(const std::string& strMovie)
+bool CEdl::ReadBeyondTV(const std::string& mediaFilePath)
{
Clear();
- std::string beyondTVFilename(URIUtils::ReplaceExtension(strMovie, URIUtils::GetExtension(strMovie) + ".chapters.xml"));
+ const std::string beyondTVFilename(URIUtils::ReplaceExtension(
+ mediaFilePath, URIUtils::GetExtension(mediaFilePath) + ".chapters.xml"));
if (!CFile::Exists(beyondTVFilename))
return false;
@@ -707,7 +709,7 @@ bool CEdl::AddEdit(const Edit& newEdit)
return true;
}
-bool CEdl::AddSceneMarker(const int iSceneMarker)
+bool CEdl::AddSceneMarker(int iSceneMarker)
{
Edit edit;
@@ -882,37 +884,35 @@ EDL::Action CEdl::GetLastEditActionType() const
return m_lastEditActionType;
}
-bool CEdl::GetNextSceneMarker(bool bPlus, const int iClock, int *iSceneMarker)
+std::optional<int> CEdl::GetNextSceneMarker(Direction direction, int clock)
{
if (!HasSceneMarker())
- return false;
+ return std::nullopt;
- int iSeek = GetTimeAfterRestoringCuts(iClock);
+ std::optional<int> sceneMarker;
+ const int seekTime = GetTimeAfterRestoringCuts(clock);
- int iDiff = 10 * 60 * 60 * 1000; // 10 hours to ms.
- bool bFound = false;
+ int diff = 10 * 60 * 60 * 1000; // 10 hours to ms.
- if (bPlus) // Find closest scene forwards
+ if (direction == Direction::FORWARD) // Find closest scene forwards
{
for (int i = 0; i < (int)m_vecSceneMarkers.size(); i++)
{
- if ((m_vecSceneMarkers[i] > iSeek) && ((m_vecSceneMarkers[i] - iSeek) < iDiff))
+ if ((m_vecSceneMarkers[i] > seekTime) && ((m_vecSceneMarkers[i] - seekTime) < diff))
{
- iDiff = m_vecSceneMarkers[i] - iSeek;
- *iSceneMarker = m_vecSceneMarkers[i];
- bFound = true;
+ diff = m_vecSceneMarkers[i] - seekTime;
+ sceneMarker = m_vecSceneMarkers[i];
}
}
}
- else // Find closest scene backwards
+ else if (direction == Direction::BACKWARD) // Find closest scene backwards
{
for (int i = 0; i < (int)m_vecSceneMarkers.size(); i++)
{
- if ((m_vecSceneMarkers[i] < iSeek) && ((iSeek - m_vecSceneMarkers[i]) < iDiff))
+ if ((m_vecSceneMarkers[i] < seekTime) && ((seekTime - m_vecSceneMarkers[i]) < diff))
{
- iDiff = iSeek - m_vecSceneMarkers[i];
- *iSceneMarker = m_vecSceneMarkers[i];
- bFound = true;
+ diff = seekTime - m_vecSceneMarkers[i];
+ sceneMarker = m_vecSceneMarkers[i];
}
}
}
@@ -922,16 +922,17 @@ bool CEdl::GetNextSceneMarker(bool bPlus, const int iClock, int *iSceneMarker)
* picked up when scene markers are added.
*/
Edit edit;
- if (bFound && InEdit(*iSceneMarker, &edit) && edit.action == Action::CUT)
- *iSceneMarker = edit.end;
+ if (sceneMarker && InEdit(sceneMarker.value(), &edit) && edit.action == Action::CUT)
+ sceneMarker = edit.end;
- return bFound;
+ return sceneMarker;
}
-std::string CEdl::MillisecondsToTimeString(const int iMilliseconds)
+std::string CEdl::MillisecondsToTimeString(int milliSeconds)
{
- std::string strTimeString = StringUtils::SecondsToTimeString((long)(iMilliseconds / 1000), TIME_FORMAT_HH_MM_SS); // milliseconds to seconds
- strTimeString += StringUtils::Format(".{:03}", iMilliseconds % 1000);
+ std::string strTimeString = StringUtils::SecondsToTimeString(
+ static_cast<long>(milliSeconds / 1000), TIME_FORMAT_HH_MM_SS); // milliseconds to seconds
+ strTimeString += StringUtils::Format(".{:03}", milliSeconds % 1000);
return strTimeString;
}
diff --git a/xbmc/cores/VideoPlayer/Edl.h b/xbmc/cores/VideoPlayer/Edl.h
index faf3e732f1..3b0279c34d 100644
--- a/xbmc/cores/VideoPlayer/Edl.h
+++ b/xbmc/cores/VideoPlayer/Edl.h
@@ -8,8 +8,10 @@
#pragma once
+#include "cores/Direction.h"
#include "cores/EdlEdit.h"
+#include <optional>
#include <string>
#include <vector>
@@ -20,10 +22,7 @@ class CEdl
public:
CEdl();
- // FIXME: remove const modifier for fFramesPerSecond as it makes no sense as it means nothing
- // for the reader of the interface, but limits the implementation
- // to not modify the parameter on stack
- bool ReadEditDecisionLists(const CFileItem& fileItem, const float fFramesPerSecond);
+ bool ReadEditDecisionLists(const CFileItem& fileItem, float fps);
void Clear();
/*!
@@ -144,15 +143,15 @@ public:
*/
EDL::Action GetLastEditActionType() const;
- // FIXME: remove const modifier for iClock as it makes no sense as it means nothing
- // for the reader of the interface, but limits the implementation
- // to not modify the parameter on stack
- bool GetNextSceneMarker(bool bPlus, const int iClock, int *iSceneMarker);
+ /*!
+ * @brief Get the next scene marker with respect to the provided clock time
+ * @param direction (the direction of the search - backward or forward)
+ * @param clock the current position of the clock
+ * @return the position of the scenemarker (nullopt if none)
+ */
+ std::optional<int> GetNextSceneMarker(Direction direction, int clock);
- // FIXME: remove const modifier as it makes no sense as it means nothing
- // for the reader of the interface, but limits the implementation
- // to not modify the parameter on stack
- static std::string MillisecondsToTimeString(const int iMilliseconds);
+ static std::string MillisecondsToTimeString(int milliSeconds);
private:
// total cut time (edl cuts) in ms
@@ -170,22 +169,10 @@ private:
*/
EDL::Action m_lastEditActionType{EDL::EDL_ACTION_NONE};
- // FIXME: remove const modifier for fFramesPerSecond as it makes no sense as it means nothing
- // for the reader of the interface, but limits the implementation
- // to not modify the parameter on stack
- bool ReadEdl(const std::string& strMovie, const float fFramesPerSecond);
- // FIXME: remove const modifier for fFramesPerSecond as it makes no sense as it means nothing
- // for the reader of the interface, but limits the implementation
- // to not modify the parameter on stack
- bool ReadComskip(const std::string& strMovie, const float fFramesPerSecond);
- // FIXME: remove const modifier for strMovie as it makes no sense as it means nothing
- // for the reader of the interface, but limits the implementation
- // to not modify the parameter on stack
- bool ReadVideoReDo(const std::string& strMovie);
- // FIXME: remove const modifier for strMovie as it makes no sense as it means nothing
- // for the reader of the interface, but limits the implementation
- // to not modify the parameter on stack
- bool ReadBeyondTV(const std::string& strMovie);
+ bool ReadEdl(const std::string& mediaFilePath, float fps);
+ bool ReadComskip(const std::string& mediaFilePath, float fps);
+ bool ReadVideoReDo(const std::string& mediaFilePath);
+ bool ReadBeyondTV(const std::string& mediaFilePath);
bool ReadPvr(const CFileItem& fileItem);
/*!
@@ -195,10 +182,7 @@ private:
*/
bool AddEdit(const EDL::Edit& newEdit);
- // FIXME: remove const modifier for strMovie as it makes no sense as it means nothing
- // for the reader of the interface, but limits the implementation
- // to not modify the parameter on stack
- bool AddSceneMarker(const int sceneMarker);
+ bool AddSceneMarker(int sceneMarker);
void MergeShortCommBreaks();
diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
index d2568bd710..be3d3a030b 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
@@ -3254,7 +3254,7 @@ void CVideoPlayer::Seek(bool bPlus, bool bLargeStep, bool bChapterOverride)
m_callback.OnPlayBackSeek(seekTarget, seekTarget - time);
}
-bool CVideoPlayer::SeekScene(bool bPlus)
+bool CVideoPlayer::SeekScene(Direction seekDirection)
{
if (!m_Edl.HasSceneMarker())
return false;
@@ -3264,18 +3264,19 @@ bool CVideoPlayer::SeekScene(bool bPlus)
* grace period applied it is impossible to go backwards past a scene marker.
*/
int64_t clock = GetTime();
- if (!bPlus && clock > 5 * 1000) // 5 seconds
+ if (seekDirection == Direction::BACKWARD && clock > 5 * 1000) // 5 seconds
clock -= 5 * 1000;
- int iScenemarker;
- if (m_Edl.GetNextSceneMarker(bPlus, clock, &iScenemarker))
+ const std::optional<int> sceneMarker =
+ m_Edl.GetNextSceneMarker(seekDirection, static_cast<int>(clock));
+ if (sceneMarker)
{
/*
* Seeking is flushed and inaccurate, just like Seek()
*/
CDVDMsgPlayerSeek::CMode mode;
- mode.time = iScenemarker;
- mode.backward = !bPlus;
+ mode.time = sceneMarker.value();
+ mode.backward = seekDirection == Direction::BACKWARD;
mode.accurate = false;
mode.restore = false;
mode.trickplay = false;
@@ -4527,7 +4528,7 @@ bool CVideoPlayer::OnAction(const CAction &action)
m_processInfo->SeekFinished(0);
return true;
}
- else if (SeekScene(true))
+ else if (SeekScene(Direction::FORWARD))
return true;
else
break;
@@ -4538,7 +4539,7 @@ bool CVideoPlayer::OnAction(const CAction &action)
m_processInfo->SeekFinished(0);
return true;
}
- else if (SeekScene(false))
+ else if (SeekScene(Direction::BACKWARD))
return true;
else
break;
diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.h b/xbmc/cores/VideoPlayer/VideoPlayer.h
index 1300b0fd4e..f340b85e83 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayer.h
+++ b/xbmc/cores/VideoPlayer/VideoPlayer.h
@@ -264,7 +264,7 @@ public:
bool IsPassthrough() const override;
bool CanSeek() const override;
void Seek(bool bPlus, bool bLargeStep, bool bChapterOverride) override;
- bool SeekScene(bool bPlus = true) override;
+ bool SeekScene(Direction seekDirection) override;
void SeekPercentage(float iPercent) override;
float GetCachePercentage() const override;
diff --git a/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp b/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp
index 7098b9144e..4516d9666c 100644
--- a/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp
+++ b/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp
@@ -84,17 +84,20 @@ TEST_F(TestEdl, TestParsingMplayerTimeBasedEDL)
const auto commbreak = edl.GetEditList().at(1);
EXPECT_EQ(commbreak.action, Action::COMM_BREAK);
// We should have a scenemarker at the commbreak start and another on commbreak end
- int time;
+ std::optional<int> time = edl.GetNextSceneMarker(Direction::FORWARD, commbreak.start - 1);
// lets cycle to the next scenemarker if starting from 1 msec before the start (or end) of the commbreak
- EXPECT_EQ(edl.GetNextSceneMarker(true, commbreak.start - 1, &time), true);
- EXPECT_EQ(edl.GetTimeWithoutCuts(time), commbreak.start);
- EXPECT_EQ(edl.GetNextSceneMarker(true, commbreak.end - 1, &time), true);
- EXPECT_EQ(edl.GetTimeWithoutCuts(time), commbreak.end);
+ EXPECT_NE(time, std::nullopt);
+ EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.start);
+ time = edl.GetNextSceneMarker(Direction::FORWARD, commbreak.end - 1);
+ EXPECT_NE(time, std::nullopt);
+ EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.end);
// same if we cycle backwards
- EXPECT_EQ(edl.GetNextSceneMarker(false, commbreak.start + 1, &time), true);
- EXPECT_EQ(edl.GetTimeWithoutCuts(time), commbreak.start);
- EXPECT_EQ(edl.GetNextSceneMarker(false, commbreak.end + 1, &time), true);
- EXPECT_EQ(edl.GetTimeWithoutCuts(time), commbreak.end);
+ time = edl.GetNextSceneMarker(Direction::BACKWARD, commbreak.start + 1);
+ EXPECT_NE(time, std::nullopt);
+ EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.start);
+ time = edl.GetNextSceneMarker(Direction::BACKWARD, commbreak.end + 1);
+ EXPECT_NE(time, std::nullopt);
+ EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.end);
// We should be in an edit if we are in the middle of a commbreak...
// lets check and confirm the edits match (after restoring cuts)
Edit thisEdit;
diff --git a/xbmc/platform/win10/CMakeLists.txt b/xbmc/platform/win10/CMakeLists.txt
index 19bc19f0e5..ff6260e36a 100644
--- a/xbmc/platform/win10/CMakeLists.txt
+++ b/xbmc/platform/win10/CMakeLists.txt
@@ -11,6 +11,7 @@ set(SOURCES CPUInfoWin10.cpp
../win32/MemUtils.cpp
../win32/pch.cpp
../win32/WIN32Util.cpp
+ ../win32/WinRtUtil.cpp
../win32/XTimeUtils.cpp)
set(HEADERS AsyncHelpers.h
@@ -29,6 +30,7 @@ set(HEADERS AsyncHelpers.h
../win32/PlatformDefs.h
../win32/resource.h
../win32/unistd.h
- ../win32/WIN32Util.h)
+ ../win32/WIN32Util.h
+ ../win32/WinRtUtil.h)
core_add_library(platform_win10)
diff --git a/xbmc/platform/win32/CMakeLists.txt b/xbmc/platform/win32/CMakeLists.txt
index 28faedb9c0..ab54d6c8b2 100644
--- a/xbmc/platform/win32/CMakeLists.txt
+++ b/xbmc/platform/win32/CMakeLists.txt
@@ -10,6 +10,7 @@ set(SOURCES CharsetConverter.cpp
PlatformWin32.cpp
WIN32Util.cpp
WindowHelper.cpp
+ WinRtUtil.cpp
XTimeUtils.cpp)
set(HEADERS CharsetConverter.h
@@ -27,6 +28,7 @@ set(HEADERS CharsetConverter.h
resource.h
unistd.h
WIN32Util.h
- WindowHelper.h)
+ WindowHelper.h
+ WinRtUtil.h)
core_add_library(platform_win32)
diff --git a/xbmc/platform/win32/WIN32Util.cpp b/xbmc/platform/win32/WIN32Util.cpp
index 29658a42a9..46726af482 100644
--- a/xbmc/platform/win32/WIN32Util.cpp
+++ b/xbmc/platform/win32/WIN32Util.cpp
@@ -11,6 +11,7 @@
#include "CompileInfo.h"
#include "ServiceBroker.h"
#include "Util.h"
+#include "WinRtUtil.h"
#include "WindowHelper.h"
#include "guilib/LocalizeStrings.h"
#include "my_ntddscsi.h"
@@ -1347,53 +1348,13 @@ HDR_STATUS CWIN32Util::ToggleWindowsHDR(DXGI_MODE_DESC& modeDesc)
return status;
}
-HDR_STATUS CWIN32Util::GetWindowsHDRStatus()
+HDR_STATUS CWIN32Util::GetWindowsHDRStatusWin32()
{
+ HDR_STATUS status = HDR_STATUS::HDR_UNKNOWN;
+
+#ifdef TARGET_WINDOWS_DESKTOP
bool advancedColorSupported = false;
bool advancedColorEnabled = false;
- HDR_STATUS status = HDR_STATUS::HDR_UNSUPPORTED;
-
-#ifdef TARGET_WINDOWS_STORE
- auto displayInformation = DisplayInformation::GetForCurrentView();
-
- if (displayInformation)
- {
- auto advancedColorInfo = displayInformation.GetAdvancedColorInfo();
-
- if (advancedColorInfo)
- {
- if (advancedColorInfo.CurrentAdvancedColorKind() == AdvancedColorKind::HighDynamicRange)
- {
- advancedColorSupported = true;
- advancedColorEnabled = true;
- }
- }
- }
- // Try to find out if the display supports HDR even if Windows HDR switch is OFF
- if (!advancedColorEnabled)
- {
- auto displayManager = DisplayManager::Create(DisplayManagerOptions::None);
-
- if (displayManager)
- {
- auto targets = displayManager.GetCurrentTargets();
-
- for (const auto& target : targets)
- {
- if (target.IsConnected())
- {
- auto displayMonitor = target.TryGetMonitor();
- if (displayMonitor.MaxLuminanceInNits() >= 400.0f)
- {
- advancedColorSupported = true;
- break;
- }
- }
- }
- displayManager.Close();
- }
- }
-#else
uint32_t pathCount = 0;
uint32_t modeCount = 0;
@@ -1451,7 +1412,6 @@ HDR_STATUS CWIN32Util::GetWindowsHDRStatus()
}
}
}
-#endif
if (!advancedColorSupported)
{
@@ -1466,10 +1426,35 @@ HDR_STATUS CWIN32Util::GetWindowsHDRStatus()
CLog::LogF(LOGDEBUG, "Display is HDR capable and current HDR status is {}",
advancedColorEnabled ? "ON" : "OFF");
}
+#endif // TARGET_WINDOWS_DESKTOP
return status;
}
+HDR_STATUS CWIN32Util::GetWindowsHDRStatus()
+{
+ HDR_STATUS status = HDR_STATUS::HDR_UNKNOWN;
+
+#ifdef TARGET_WINDOWS_STORE
+ if (CSysInfo::GetWindowsDeviceFamily() == CSysInfo::Xbox &&
+ HDR_STATUS::HDR_UNKNOWN != (status = CWinRtUtil::GetWindowsHDRStatus()))
+ return status;
+
+ // Not Xbox or detection failure: fallback to traditional UWP method
+ status = CWinRtUtil::GetWindowsHDRStatusUWP();
+ return status == HDR_STATUS::HDR_UNKNOWN ? HDR_STATUS::HDR_UNSUPPORTED : status;
+#else
+ // WinRT detection available for Win 11 22621 and above.
+ if (CSysInfo::IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin11_22H2) &&
+ HDR_STATUS::HDR_UNKNOWN != (status = CWinRtUtil::GetWindowsHDRStatus()))
+ return status;
+
+ // Not Win11 or detection failure: fallback to traditional Win32 method
+ status = GetWindowsHDRStatusWin32();
+ return status == HDR_STATUS::HDR_UNKNOWN ? HDR_STATUS::HDR_UNSUPPORTED : status;
+#endif
+}
+
/*!
* \brief Retrieve from the system the max luminance of SDR content in HDR.
*
diff --git a/xbmc/platform/win32/WIN32Util.h b/xbmc/platform/win32/WIN32Util.h
index 054ca262bd..33033fb431 100644
--- a/xbmc/platform/win32/WIN32Util.h
+++ b/xbmc/platform/win32/WIN32Util.h
@@ -105,4 +105,7 @@ public:
* Undefined results when the strings are not formatted properly.
*/
static bool IsDriverVersionAtLeast(const std::string& version1, const std::string& version2);
+
+private:
+ static HDR_STATUS GetWindowsHDRStatusWin32();
};
diff --git a/xbmc/platform/win32/WinRtUtil.cpp b/xbmc/platform/win32/WinRtUtil.cpp
new file mode 100644
index 0000000000..ce239a722e
--- /dev/null
+++ b/xbmc/platform/win32/WinRtUtil.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2024 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 "WinRtUtil.h"
+
+#include "rendering/dx/DirectXHelper.h"
+#include "utils/SystemInfo.h"
+#include "utils/log.h"
+
+#ifdef TARGET_WINDOWS_DESKTOP
+#include <Windows.Graphics.Display.Interop.h>
+
+#else
+#include <winrt/Windows.Devices.Display.Core.h>
+
+using namespace winrt::Windows::Devices::Display::Core;
+#endif
+
+#include <winrt/Windows.Graphics.Display.h>
+
+using namespace winrt::Windows::Graphics::Display;
+
+#ifdef TARGET_WINDOWS_DESKTOP
+extern HWND g_hWnd;
+#endif
+
+static constexpr std::string_view AdvancedColorKindToString(AdvancedColorKind kind)
+{
+ switch (kind)
+ {
+ case AdvancedColorKind::StandardDynamicRange:
+ return "SDR";
+ case AdvancedColorKind::WideColorGamut:
+ return "WCG";
+ case AdvancedColorKind::HighDynamicRange:
+ return "HDR";
+ default:
+ return "unknown";
+ }
+}
+
+static void LogAdvancedColorInfo(AdvancedColorInfo colorInfo)
+{
+ std::string availableKinds;
+ static constexpr std::array<AdvancedColorKind, 3> kinds{AdvancedColorKind::StandardDynamicRange,
+ AdvancedColorKind::WideColorGamut,
+ AdvancedColorKind::HighDynamicRange};
+
+ for (const AdvancedColorKind& kind : kinds)
+ {
+ if (colorInfo.IsAdvancedColorKindAvailable(kind))
+ availableKinds.append(AdvancedColorKindToString(kind)).append(" ");
+ }
+
+ CLog::LogF(LOGDEBUG, "Current advanced color kind: {}, supported kinds: {}",
+ AdvancedColorKindToString(colorInfo.CurrentAdvancedColorKind()), availableKinds);
+}
+
+HDR_STATUS CWinRtUtil::GetWindowsHDRStatus()
+{
+ DisplayInformation displayInformation{nullptr};
+
+#ifdef TARGET_WINDOWS_STORE
+ displayInformation = DisplayInformation::GetForCurrentView();
+
+ if (!displayInformation)
+ {
+ CLog::LogF(LOGERROR, "unable to retrieve DisplayInformation.");
+ return HDR_STATUS::HDR_UNKNOWN;
+ }
+#else
+ auto factory{
+ winrt::try_get_activation_factory<DisplayInformation, IDisplayInformationStaticsInterop>()};
+
+ if (!factory)
+ {
+ CLog::LogF(LOGERROR,
+ "unable to activate IDisplayInformationStaticsInterop. Windows version too low?");
+ return HDR_STATUS::HDR_UNKNOWN;
+ }
+
+ HMONITOR hm{};
+ if (g_hWnd)
+ {
+ RECT rect{};
+
+ if (FALSE == GetWindowRect(g_hWnd, &rect))
+ {
+ CLog::LogF(LOGERROR, "unable to retrieve window rect, error {}",
+ DX::GetErrorDescription(GetLastError()));
+ return HDR_STATUS::HDR_UNKNOWN;
+ }
+
+ hm = MonitorFromRect(&rect, MONITOR_DEFAULTTONULL);
+
+ if (hm == NULL)
+ {
+ CLog::LogF(LOGERROR, "unable to retrieve monitor intersecting with application window");
+ return HDR_STATUS::HDR_UNKNOWN;
+ }
+ }
+ else
+ {
+ POINT point{};
+
+ hm = MonitorFromPoint(point, MONITOR_DEFAULTTONULL);
+
+ if (hm == NULL)
+ {
+ CLog::LogF(LOGERROR, "unable to retrieve primary monitor");
+ return HDR_STATUS::HDR_UNKNOWN;
+ }
+ }
+
+ HRESULT hr = factory->GetForMonitor(hm, winrt::guid_of<DisplayInformation>(),
+ winrt::put_abi(displayInformation));
+ if (FAILED(hr))
+ {
+ CLog::LogF(LOGERROR, "unable to retrieve DisplayInformation for window, error {}",
+ DX::GetErrorDescription(hr));
+ return HDR_STATUS::HDR_UNKNOWN;
+ }
+#endif
+
+ AdvancedColorInfo colorInfo{displayInformation.GetAdvancedColorInfo()};
+
+ if (!colorInfo)
+ {
+ CLog::LogF(LOGERROR, "unable to retrieve advanced color info");
+ return HDR_STATUS::HDR_UNKNOWN;
+ }
+
+ LogAdvancedColorInfo(colorInfo);
+
+ if (colorInfo.CurrentAdvancedColorKind() == AdvancedColorKind::HighDynamicRange)
+ return HDR_STATUS::HDR_ON;
+
+ // IsAdvancedColorKindAvailable works for desktop Windows 11 22H2+ and Xbox
+ if (colorInfo.IsAdvancedColorKindAvailable(AdvancedColorKind::HighDynamicRange))
+ return HDR_STATUS::HDR_OFF;
+ else
+ return HDR_STATUS::HDR_UNSUPPORTED;
+}
+
+HDR_STATUS CWinRtUtil::GetWindowsHDRStatusUWP()
+{
+#ifdef TARGET_WINDOWS_STORE
+ // Legacy detection, useful for UWP desktop at this point
+ DisplayInformation displayInformation = DisplayInformation::GetForCurrentView();
+
+ if (!displayInformation)
+ {
+ CLog::LogF(LOGERROR, "unable to retrieve DisplayInformation.");
+ return HDR_STATUS::HDR_UNKNOWN;
+ }
+
+ AdvancedColorInfo colorInfo{displayInformation.GetAdvancedColorInfo()};
+
+ if (!colorInfo)
+ {
+ CLog::LogF(LOGERROR, "unable to retrieve advanced color info");
+ return HDR_STATUS::HDR_UNKNOWN;
+ }
+
+ if (colorInfo.CurrentAdvancedColorKind() == AdvancedColorKind::HighDynamicRange)
+ return HDR_STATUS::HDR_ON;
+
+ // Detects any hdr-capable screen connected to the system, not necessarily the one that contains
+ // the Kodi window
+ bool hdrSupported{false};
+ auto displayManager = DisplayManager::Create(DisplayManagerOptions::None);
+
+ if (displayManager)
+ {
+ auto targets = displayManager.GetCurrentTargets();
+
+ for (const auto& target : targets)
+ {
+ if (target.IsConnected())
+ {
+ auto displayMonitor = target.TryGetMonitor();
+ if (displayMonitor.MaxLuminanceInNits() >= 400.0f)
+ {
+ hdrSupported = true;
+ break;
+ }
+ }
+ }
+ displayManager.Close();
+ }
+
+ if (hdrSupported)
+ return HDR_STATUS::HDR_OFF;
+#endif // TARGET_WINDOWS_STORE
+
+ return HDR_STATUS::HDR_UNSUPPORTED;
+}
diff --git a/xbmc/platform/win32/WinRtUtil.h b/xbmc/platform/win32/WinRtUtil.h
new file mode 100644
index 0000000000..7d58fe7dc1
--- /dev/null
+++ b/xbmc/platform/win32/WinRtUtil.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 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 "HDRStatus.h"
+
+class CWinRtUtil
+{
+private:
+ CWinRtUtil() = default;
+ ~CWinRtUtil() = default;
+
+public:
+ static HDR_STATUS GetWindowsHDRStatus();
+ static HDR_STATUS GetWindowsHDRStatusUWP();
+};
diff --git a/xbmc/rendering/dx/DeviceResources.h b/xbmc/rendering/dx/DeviceResources.h
index b0ed0f4882..a512e5a0bb 100644
--- a/xbmc/rendering/dx/DeviceResources.h
+++ b/xbmc/rendering/dx/DeviceResources.h
@@ -17,6 +17,7 @@
#include <concrt.h>
#include <dxgi1_5.h>
+#include <winrt/windows.foundation.h>
#include <wrl.h>
#include <wrl/client.h>
diff --git a/xbmc/rendering/dx/DirectXHelper.h b/xbmc/rendering/dx/DirectXHelper.h
index 779b8751d5..368bfcbad9 100644
--- a/xbmc/rendering/dx/DirectXHelper.h
+++ b/xbmc/rendering/dx/DirectXHelper.h
@@ -202,18 +202,4 @@ namespace DX
const std::string DXGIColorSpaceTypeToString(DXGI_COLOR_SPACE_TYPE type);
const std::string D3D11VideoProcessorFormatSupportToString(
D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT value);
-}
-
-#ifdef TARGET_WINDOWS_DESKTOP
-namespace winrt
-{
- namespace Windows
- {
- namespace Foundation
- {
- typedef DX::SizeGen<float> Size;
- typedef DX::SizeGen<int> SizeInt;
- }
- }
-}
-#endif
+ } // namespace DX