aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/skin.estuary/xml/Variables.xml2
-rw-r--r--cmake/treedata/common/subdirs.txt1
-rw-r--r--tools/android/packaging/Makefile.in2
-rw-r--r--tools/android/packaging/xbmc/res/xml/searchable.xml16
-rw-r--r--tools/depends/native/expat/EXPAT-VERSION4
-rw-r--r--tools/depends/native/openssl/OPENSSL-VERSION4
-rw-r--r--tools/depends/target/expat/EXPAT-VERSION4
-rw-r--r--tools/depends/target/openssl/OPENSSL-VERSION4
-rw-r--r--xbmc/ContextMenuItem.h1
-rw-r--r--xbmc/FileItem.cpp83
-rw-r--r--xbmc/FileItem.h3
-rw-r--r--xbmc/addons/AddonManager.h1
-rw-r--r--xbmc/addons/IAddon.h1
-rw-r--r--xbmc/addons/interfaces/Filesystem.cpp5
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp58
-rw-r--r--xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h2
-rw-r--r--xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h2
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp2
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h2
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp2
-rw-r--r--xbmc/cores/VideoPlayer/VideoPlayer.cpp3
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp2
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp11
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/ConversionMatrix.h1
-rw-r--r--xbmc/dialogs/GUIDialogMediaSource.cpp14
-rw-r--r--xbmc/filesystem/DirectoryFactory.cpp9
-rw-r--r--xbmc/filesystem/PlaylistFileDirectory.cpp10
-rw-r--r--xbmc/guilib/FFmpegImage.h2
-rw-r--r--xbmc/guilib/GUIComponent.cpp4
-rw-r--r--xbmc/guilib/GUIComponent.h2
-rw-r--r--xbmc/guilib/handlers/CMakeLists.txt7
-rw-r--r--xbmc/guilib/handlers/GUIAnnouncementHandlerContainer.cpp16
-rw-r--r--xbmc/guilib/handlers/GUIAnnouncementHandlerContainer.h29
-rw-r--r--xbmc/guilib/handlers/sources/GUISourcesAnnouncementHandler.cpp42
-rw-r--r--xbmc/guilib/handlers/sources/GUISourcesAnnouncementHandler.h26
-rw-r--r--xbmc/input/keymaps/remote/IRTranslator.h1
-rw-r--r--xbmc/interfaces/IAnnouncer.h44
-rw-r--r--xbmc/messaging/ThreadMessage.h1
-rw-r--r--xbmc/network/ZeroconfBrowser.h3
-rw-r--r--xbmc/network/mdns/ZeroconfBrowserMDNS.cpp14
-rw-r--r--xbmc/network/upnp/UPnP.cpp21
-rw-r--r--xbmc/network/upnp/UPnPRenderer.cpp1
-rw-r--r--xbmc/platform/android/PlatformAndroid.cpp3
-rw-r--r--xbmc/platform/android/activity/XBMCApp.cpp37
-rw-r--r--xbmc/platform/android/activity/XBMCApp.h7
-rw-r--r--xbmc/platform/android/network/ZeroconfBrowserAndroid.cpp13
-rw-r--r--xbmc/platform/android/storage/AndroidStorageProvider.cpp45
-rw-r--r--xbmc/platform/android/storage/AndroidStorageProvider.h8
-rw-r--r--xbmc/platform/darwin/network/ZeroconfBrowserDarwin.cpp13
-rw-r--r--xbmc/platform/linux/storage/UDevProvider.cpp5
-rw-r--r--xbmc/playlists/PlayListFactory.cpp14
-rw-r--r--xbmc/playlists/PlayListFactory.h1
-rw-r--r--xbmc/pvr/PVRContextMenus.cpp78
-rw-r--r--xbmc/pvr/epg/Epg.cpp3
-rw-r--r--xbmc/pvr/filesystem/PVRGUIDirectory.cpp48
-rw-r--r--xbmc/pvr/filesystem/PVRGUIDirectory.h8
-rw-r--r--xbmc/pvr/guilib/PVRGUIActionsTimers.cpp37
-rw-r--r--xbmc/pvr/timers/PVRTimerInfoTag.cpp9
-rw-r--r--xbmc/pvr/timers/PVRTimers.cpp6
-rw-r--r--xbmc/settings/AdvancedSettings.h1
-rw-r--r--xbmc/storage/DetectDVDType.cpp7
-rw-r--r--xbmc/storage/DetectDVDType.h1
-rw-r--r--xbmc/utils/Archive.h1
-rw-r--r--xbmc/utils/CharArrayParser.cpp10
-rw-r--r--xbmc/utils/EGLFence.cpp8
-rw-r--r--xbmc/video/VideoDatabase.cpp2
-rw-r--r--xbmc/video/VideoInfoScanner.cpp5
-rw-r--r--xbmc/video/VideoUtils.cpp103
-rw-r--r--xbmc/video/VideoUtils.h7
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoInfo.cpp33
-rw-r--r--xbmc/video/test/TestVideoUtils.cpp62
-rw-r--r--xbmc/video/windows/GUIWindowVideoBase.cpp1
-rw-r--r--xbmc/windowing/gbm/drm/DRMAtomic.cpp8
-rw-r--r--xbmc/windowing/gbm/drm/DRMObject.cpp30
-rw-r--r--xbmc/windowing/gbm/drm/DRMObject.h3
-rw-r--r--xbmc/windowing/gbm/drm/DRMUtils.cpp169
-rw-r--r--xbmc/windowing/gbm/drm/DRMUtils.h5
77 files changed, 843 insertions, 410 deletions
diff --git a/addons/skin.estuary/xml/Variables.xml b/addons/skin.estuary/xml/Variables.xml
index afb70923e5..49382061a9 100644
--- a/addons/skin.estuary/xml/Variables.xml
+++ b/addons/skin.estuary/xml/Variables.xml
@@ -703,8 +703,10 @@
</variable>
<variable name="VideoListThumbVar">
<value condition="!String.IsEmpty(Container(6).ListItem.Art(landscape))">$INFO[Container(6).ListItem.Art(landscape)]</value>
+ <value condition="!String.IsEmpty(Container(6).ListItem.Art(poster))">$INFO[Container(6).ListItem.Art(poster)]</value>
<value condition="!String.IsEmpty(Container(6).ListItem.Art(thumb))">$INFO[Container(6).ListItem.Art(thumb)]</value>
<value condition="!String.IsEmpty(Container(50).ListItem.Art(landscape))">$INFO[Container(50).ListItem.Art(landscape)]</value>
+ <value condition="!String.IsEmpty(Container(50).ListItem.Art(poster))">$INFO[Container(50).ListItem.Art(poster)]</value>
<value condition="!String.IsEmpty(Container(50).ListItem.Art(thumb))">$INFO[Container(50).ListItem.Art(thumb)]</value>
<value>$INFO[ListItem.Art(thumb)]</value>
</variable>
diff --git a/cmake/treedata/common/subdirs.txt b/cmake/treedata/common/subdirs.txt
index 00bd9396e5..f4e46076fb 100644
--- a/cmake/treedata/common/subdirs.txt
+++ b/cmake/treedata/common/subdirs.txt
@@ -16,6 +16,7 @@ xbmc/dialogs dialogs
xbmc/favourites favourites
xbmc/guilib guilib
xbmc/guilib/guiinfo guilib_guiinfo
+xbmc/guilib/handlers guilib_announcement_handlers
xbmc/guilib/listproviders guilib_listproviders
xbmc/imagefiles imagefiles
xbmc/messaging messaging
diff --git a/tools/android/packaging/Makefile.in b/tools/android/packaging/Makefile.in
index d0e9d3cc7a..d29675783f 100644
--- a/tools/android/packaging/Makefile.in
+++ b/tools/android/packaging/Makefile.in
@@ -57,7 +57,7 @@ python: | xbmc/assets
cd xbmc/assets/python@PYTHON_VERSION@/lib/python@PYTHON_VERSION@/; rm -rf test config config-@PYTHON_VERSION@ lib-dynload ; find . -name "*.so" -exec rm -f {} \;
res:
- mkdir -p xbmc/res xbmc/res/values
+ mkdir -p xbmc/res xbmc/res/values xbmc/res/xml
cp -rfp media/mipmap-* xbmc/res/
cp -fp $(CMAKE_SOURCE_DIR)/media/applaunch_screen.png xbmc/res/drawable/
cp -fp $(CMAKE_SOURCE_DIR)/media/applaunch_screen.png xbmc/res/drawable-xxxhdpi/
diff --git a/tools/android/packaging/xbmc/res/xml/searchable.xml b/tools/android/packaging/xbmc/res/xml/searchable.xml
deleted file mode 100644
index af66a877fe..0000000000
--- a/tools/android/packaging/xbmc/res/xml/searchable.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<searchable xmlns:android="http://schemas.android.com/apk/res/android"
- android:label="@string/app_name"
- android:hint="@string/search_hint"
-
- android:searchSuggestAuthority="org.xbmc.kodi.media"
- android:searchSuggestPath="suggestions"
-
- android:searchSuggestIntentAction="android.intent.action.GET_CONTENT"
- android:searchSuggestIntentData="content://org.xbmc.kodi.media/intent"
-
- android:includeInGlobalSearch="true"
- android:searchSettingsDescription="Media"
- android:searchSuggestThreshold="3"
- >
-</searchable> \ No newline at end of file
diff --git a/tools/depends/native/expat/EXPAT-VERSION b/tools/depends/native/expat/EXPAT-VERSION
index 3631ff3f5b..dd337f57dc 100644
--- a/tools/depends/native/expat/EXPAT-VERSION
+++ b/tools/depends/native/expat/EXPAT-VERSION
@@ -1,5 +1,5 @@
LIBNAME=expat
-VERSION=2.6.2
+VERSION=2.6.3
SOURCE=$(LIBNAME)-$(VERSION)
ARCHIVE=$(SOURCE).tar.xz
-SHA512=47b60967d6346d330dded87ea1a2957aa7d34dd825043386a89aa131054714f618ede57bfe97cf6caa40582a4bc67e198d2a915e7d8dbe8ee4f581857c2e3c2e
+SHA512=e02c4ad88f9d539258aa1c1db71ded7770a8f12c77b5535e5b34f040ae5b1361ef23132f16d96bdb7c096a83acd637a7c907916bdfcc6d5cfb9e35d04020ca0b
diff --git a/tools/depends/native/openssl/OPENSSL-VERSION b/tools/depends/native/openssl/OPENSSL-VERSION
index 424c6d4036..a7b9b2c717 100644
--- a/tools/depends/native/openssl/OPENSSL-VERSION
+++ b/tools/depends/native/openssl/OPENSSL-VERSION
@@ -1,4 +1,4 @@
LIBNAME=openssl
-VERSION=3.0.13
+VERSION=3.0.15
ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
-SHA512=22f4096781f0b075f5bf81bd39a0f97e111760dfa73b6f858f6bb54968a7847944d74969ae10f9a51cc21a2f4af20d9a4c463649dc824f5e439e196d6764c4f9
+SHA512=acd80f2f7924d90c1416946a5c61eff461926ad60f4821bb6b08845ea18f8452fd5e88a2c2c5bd0d7590a792cb8341a3f3be042fd0a5b6c9c1b84a497c347bbf
diff --git a/tools/depends/target/expat/EXPAT-VERSION b/tools/depends/target/expat/EXPAT-VERSION
index 571fe9f0e6..ba82abe72f 100644
--- a/tools/depends/target/expat/EXPAT-VERSION
+++ b/tools/depends/target/expat/EXPAT-VERSION
@@ -1,6 +1,6 @@
LIBNAME=expat
-VERSION=2.6.2
+VERSION=2.6.3
SOURCE=$(LIBNAME)-$(VERSION)
ARCHIVE=$(SOURCE).tar.xz
-SHA512=47b60967d6346d330dded87ea1a2957aa7d34dd825043386a89aa131054714f618ede57bfe97cf6caa40582a4bc67e198d2a915e7d8dbe8ee4f581857c2e3c2e
+SHA512=e02c4ad88f9d539258aa1c1db71ded7770a8f12c77b5535e5b34f040ae5b1361ef23132f16d96bdb7c096a83acd637a7c907916bdfcc6d5cfb9e35d04020ca0b
BYPRODUCT=libexpat.a
diff --git a/tools/depends/target/openssl/OPENSSL-VERSION b/tools/depends/target/openssl/OPENSSL-VERSION
index 424c6d4036..a7b9b2c717 100644
--- a/tools/depends/target/openssl/OPENSSL-VERSION
+++ b/tools/depends/target/openssl/OPENSSL-VERSION
@@ -1,4 +1,4 @@
LIBNAME=openssl
-VERSION=3.0.13
+VERSION=3.0.15
ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
-SHA512=22f4096781f0b075f5bf81bd39a0f97e111760dfa73b6f858f6bb54968a7847944d74969ae10f9a51cc21a2f4af20d9a4c463649dc824f5e439e196d6764c4f9
+SHA512=acd80f2f7924d90c1416946a5c61eff461926ad60f4821bb6b08845ea18f8452fd5e88a2c2c5bd0d7590a792cb8341a3f3be042fd0a5b6c9c1b84a497c347bbf
diff --git a/xbmc/ContextMenuItem.h b/xbmc/ContextMenuItem.h
index aee6d82e71..6577de3224 100644
--- a/xbmc/ContextMenuItem.h
+++ b/xbmc/ContextMenuItem.h
@@ -8,6 +8,7 @@
#pragma once
+#include <cstdint>
#include <map>
#include <memory>
#include <string>
diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp
index dcc28288e4..a3fa357232 100644
--- a/xbmc/FileItem.cpp
+++ b/xbmc/FileItem.cpp
@@ -2354,89 +2354,6 @@ const std::shared_ptr<PVR::CPVRChannel> CFileItem::GetPVRChannelInfoTag() const
: std::shared_ptr<CPVRChannel>();
}
-std::string CFileItem::FindTrailer() const
-{
- std::string strFile2;
- std::string strFile = m_strPath;
- if (IsStack())
- {
- std::string strPath;
- URIUtils::GetParentPath(m_strPath,strPath);
- CStackDirectory dir;
- std::string strPath2;
- strPath2 = dir.GetStackedTitlePath(strFile);
- strFile = URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strPath2));
- CFileItem item(dir.GetFirstStackedFile(m_strPath),false);
- std::string strTBNFile(URIUtils::ReplaceExtension(ART::GetTBNFile(item), "-trailer"));
- strFile2 = URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strTBNFile));
- }
- if (URIUtils::IsInRAR(strFile) || URIUtils::IsInZIP(strFile))
- {
- std::string strPath = URIUtils::GetDirectory(strFile);
- std::string strParent;
- URIUtils::GetParentPath(strPath,strParent);
- strFile = URIUtils::AddFileToFolder(strParent,URIUtils::GetFileName(m_strPath));
- }
-
- // no local trailer available for these
- if (NETWORK::IsInternetStream(*this) || URIUtils::IsUPnP(strFile) ||
- URIUtils::IsBluray(strFile) || IsLiveTV() || IsPlugin() || IsDVD())
- return "";
-
- std::string strDir = URIUtils::GetDirectory(strFile);
- CFileItemList items;
- CDirectory::GetDirectory(strDir, items, CServiceBroker::GetFileExtensionProvider().GetVideoExtensions(), DIR_FLAG_READ_CACHE | DIR_FLAG_NO_FILE_INFO | DIR_FLAG_NO_FILE_DIRS);
- URIUtils::RemoveExtension(strFile);
- strFile += "-trailer";
- std::string strFile3 = URIUtils::AddFileToFolder(strDir, "movie-trailer");
-
- // Precompile our REs
- VECCREGEXP matchRegExps;
- CRegExp tmpRegExp(true, CRegExp::autoUtf8);
- const std::vector<std::string>& strMatchRegExps = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_trailerMatchRegExps;
-
- std::vector<std::string>::const_iterator strRegExp = strMatchRegExps.begin();
- while (strRegExp != strMatchRegExps.end())
- {
- if (tmpRegExp.RegComp(*strRegExp))
- {
- matchRegExps.push_back(tmpRegExp);
- }
- ++strRegExp;
- }
-
- std::string strTrailer;
- for (int i = 0; i < items.Size(); i++)
- {
- std::string strCandidate = items[i]->m_strPath;
- URIUtils::RemoveExtension(strCandidate);
- if (StringUtils::EqualsNoCase(strCandidate, strFile) ||
- StringUtils::EqualsNoCase(strCandidate, strFile2) ||
- StringUtils::EqualsNoCase(strCandidate, strFile3))
- {
- strTrailer = items[i]->m_strPath;
- break;
- }
- else
- {
- VECCREGEXP::iterator expr = matchRegExps.begin();
-
- while (expr != matchRegExps.end())
- {
- if (expr->RegFind(strCandidate) != -1)
- {
- strTrailer = items[i]->m_strPath;
- i = items.Size();
- break;
- }
- ++expr;
- }
- }
- }
-
- return strTrailer;
-}
-
VideoDbContentType CFileItem::GetVideoContentType() const
{
VideoDbContentType type = VideoDbContentType::MOVIES;
diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h
index 635c964d8d..ffdac95d49 100644
--- a/xbmc/FileItem.h
+++ b/xbmc/FileItem.h
@@ -448,9 +448,6 @@ public:
*/
std::string GetLocalMetadataPath() const;
- // finds a matching local trailer file
- std::string FindTrailer() const;
-
bool LoadMusicTag();
bool LoadGameTag();
diff --git a/xbmc/addons/AddonManager.h b/xbmc/addons/AddonManager.h
index fd7ee70f66..0679ffd81f 100644
--- a/xbmc/addons/AddonManager.h
+++ b/xbmc/addons/AddonManager.h
@@ -11,6 +11,7 @@
#include "threads/CriticalSection.h"
#include "utils/EventStream.h"
+#include <cstdint>
#include <map>
#include <memory>
#include <mutex>
diff --git a/xbmc/addons/IAddon.h b/xbmc/addons/IAddon.h
index 0bc383055f..d242f60f0e 100644
--- a/xbmc/addons/IAddon.h
+++ b/xbmc/addons/IAddon.h
@@ -8,6 +8,7 @@
#pragma once
+#include <cstdint>
#include <map>
#include <memory>
#include <string>
diff --git a/xbmc/addons/interfaces/Filesystem.cpp b/xbmc/addons/interfaces/Filesystem.cpp
index 9f22b67ecc..eb35cb7b54 100644
--- a/xbmc/addons/interfaces/Filesystem.cpp
+++ b/xbmc/addons/interfaces/Filesystem.cpp
@@ -151,8 +151,11 @@ unsigned int Interface_Filesystem::TranslateFileReadBitsToKodi(unsigned int addo
kodiFlags |= READ_AUDIO_VIDEO;
if (addonFlags & ADDON_READ_AFTER_WRITE)
kodiFlags |= READ_AFTER_WRITE;
- if (addonFlags & READ_REOPEN)
+ if (addonFlags & ADDON_READ_REOPEN)
kodiFlags |= READ_REOPEN;
+ //! @todo Add ADDON_READ_NO_BUFFER to filesystem.h in the binary addon devkit
+ if (addonFlags & READ_NO_BUFFER)
+ kodiFlags |= READ_NO_BUFFER;
return kodiFlags;
}
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp
index 5877e9f319..02357c123d 100644
--- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp
@@ -254,8 +254,7 @@ unsigned int CAESinkWASAPI::AddPackets(uint8_t **data, unsigned int frames, unsi
return 0;
HRESULT hr;
- BYTE *buf;
- DWORD flags = 0;
+ BYTE* buf;
#ifndef _DEBUG
LARGE_INTEGER timerStart;
@@ -293,9 +292,8 @@ unsigned int CAESinkWASAPI::AddPackets(uint8_t **data, unsigned int frames, unsi
return INT_MAX;
}
- memset(buf, 0, NumFramesRequested * m_format.m_frameSize); //fill buffer with silence
-
- hr = m_pRenderClient->ReleaseBuffer(NumFramesRequested, flags); //pass back to audio driver
+ hr = m_pRenderClient->ReleaseBuffer(NumFramesRequested,
+ AUDCLNT_BUFFERFLAGS_SILENT); //pass back to audio driver
if (FAILED(hr))
{
#ifdef _DEBUG
@@ -359,7 +357,7 @@ unsigned int CAESinkWASAPI::AddPackets(uint8_t **data, unsigned int frames, unsi
NumFramesRequested * m_format.m_frameSize);
m_bufferPtr = 0;
- hr = m_pRenderClient->ReleaseBuffer(NumFramesRequested, flags); //pass back to audio driver
+ hr = m_pRenderClient->ReleaseBuffer(NumFramesRequested, 0); //pass back to audio driver
if (FAILED(hr))
{
#ifdef _DEBUG
@@ -396,7 +394,10 @@ void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool fo
deviceInfo.m_channels.Reset();
deviceInfo.m_dataFormats.clear();
deviceInfo.m_sampleRates.clear();
+ deviceInfo.m_streamTypes.clear();
deviceChannels.Reset();
+ add192 = false;
+ add48 = false;
for (unsigned int c = 0; c < WASAPI_SPEAKER_COUNT; c++)
{
@@ -592,8 +593,23 @@ void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool fo
wfxex.dwChannelMask = KSAUDIO_SPEAKER_STEREO;
wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
- wfxex.Format.wBitsPerSample = 16;
- wfxex.Samples.wValidBitsPerSample = 16;
+
+ // 16 bits is most widely supported and likely to have the widest range of sample rates
+ if (deviceInfo.m_dataFormats.empty() ||
+ std::find(deviceInfo.m_dataFormats.cbegin(), deviceInfo.m_dataFormats.cend(),
+ AE_FMT_S16NE) != deviceInfo.m_dataFormats.cend())
+ {
+ wfxex.Format.wBitsPerSample = 16;
+ wfxex.Samples.wValidBitsPerSample = 16;
+ }
+ else
+ {
+ const AEDataFormat fmt = deviceInfo.m_dataFormats.front();
+ wfxex.Format.wBitsPerSample = CAEUtil::DataFormatToBits(fmt);
+ wfxex.Samples.wValidBitsPerSample =
+ (fmt == AE_FMT_S24NE4MSB ? 24 : wfxex.Format.wBitsPerSample);
+ }
+
wfxex.Format.nChannels = 2;
wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
@@ -745,17 +761,17 @@ bool CAESinkWASAPI::InitializeExclusive(AEAudioFormat &format)
else if (format.m_dataFormat == AE_FMT_RAW) //No sense in trying other formats for passthrough.
return false;
- CLog::Log(LOGWARNING,
- "AESinkWASAPI: IsFormatSupported failed ({}) - trying to find a compatible format",
- WASAPIErrToStr(hr));
+ CLog::LogF(LOGWARNING,
+ "format {} not supported by the device - trying to find a compatible format",
+ CAEUtil::DataFormatToStr(format.m_dataFormat));
requestedChannels = wfxex.Format.nChannels;
desired_map = CAESinkFactoryWin::SpeakerMaskFromAEChannels(format.m_channelLayout);
/* The requested format is not supported by the device. Find something that works */
- CLog::Log(LOGWARNING,
- "AESinkWASAPI: Input channels are [{}] - Trying to find a matching output layout",
- std::string(format.m_channelLayout));
+ CLog::LogF(LOGWARNING, "Input channels are [{}] - Trying to find a matching output layout",
+ std::string(format.m_channelLayout));
+
for (int layout = -1; layout <= (int)ARRAYSIZE(layoutsList); layout++)
{
// if requested layout is not supported, try standard layouts which contain
@@ -886,6 +902,20 @@ initialize:
format.m_sampleRate = wfxex.Format.nSamplesPerSec; //PCM: Sample rate. RAW: Link speed
format.m_frameSize = (wfxex.Format.wBitsPerSample >> 3) * wfxex.Format.nChannels;
+ ComPtr<IAudioClient2> audioClient2;
+ if (SUCCEEDED(m_pAudioClient.As(&audioClient2)))
+ {
+ AudioClientProperties props = {};
+ props.cbSize = sizeof(props);
+ // ForegroundOnlyMedia/BackgroundCapableMedia replaced in Windows 10 by Movie/Media
+ props.eCategory = CSysInfo::IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin10)
+ ? AudioCategory_Media
+ : AudioCategory_ForegroundOnlyMedia;
+
+ if (FAILED(hr = audioClient2->SetClientProperties(&props)))
+ CLog::LogF(LOGERROR, "unable to set audio category, {}", WASAPIErrToStr(hr));
+ }
+
REFERENCE_TIME audioSinkBufferDurationMsec, hnsLatency;
audioSinkBufferDurationMsec = (REFERENCE_TIME)500000;
diff --git a/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h b/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h
index 8d153ab5c2..132b71218c 100644
--- a/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h
+++ b/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h
@@ -11,6 +11,8 @@
#include "IRetroPlayerStream.h"
#include "cores/RetroPlayer/RetroPlayerTypes.h"
+#include <cstdint>
+
extern "C"
{
#include <libavutil/pixfmt.h>
diff --git a/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h b/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h
index b83ee8ca68..dca6e82177 100644
--- a/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h
+++ b/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h
@@ -54,6 +54,8 @@ public:
virtual const VideoPicture& GetPicture() const { return m_picture; }
virtual uint32_t GetWidth() const { return GetPicture().iWidth; }
virtual uint32_t GetHeight() const { return GetPicture().iHeight; }
+ virtual uint32_t GetXOffset() const { return GetPicture().m_xOffset; }
+ virtual uint32_t GetYOffset() const { return GetPicture().m_yOffset; }
virtual AVDRMFrameDescriptor* GetDescriptor() const = 0;
virtual bool IsValid() const { return true; }
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp
index 495d6a25f5..a5468d12a0 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp
@@ -58,6 +58,8 @@ void VideoPicture::Reset()
iWidth = 0;
iHeight = 0;
+ m_xOffset = 0;
+ m_yOffset = 0;
iDisplayWidth = 0;
iDisplayHeight = 0;
}
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h
index ca83b1a04f..f3373612e8 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h
@@ -75,6 +75,8 @@ public:
unsigned int iWidth;
unsigned int iHeight;
+ unsigned int m_xOffset{0};
+ unsigned int m_yOffset{0};
unsigned int iDisplayWidth; //< width of the picture without black bars
unsigned int iDisplayHeight; //< height of the picture without black bars
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
index eb2943bb8c..0d407043dd 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
@@ -505,6 +505,8 @@ void CDVDVideoCodecDRMPRIME::SetPictureParams(VideoPicture* pVideoPicture)
{
pVideoPicture->iWidth = m_pFrame->width;
pVideoPicture->iHeight = m_pFrame->height;
+ pVideoPicture->m_xOffset = m_pFrame->crop_left;
+ pVideoPicture->m_yOffset = m_pFrame->crop_top;
double aspect_ratio = 0;
AVRational pixel_aspect = m_pFrame->sample_aspect_ratio;
diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
index 87a9f7240e..5a20ca0fff 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
@@ -792,7 +792,8 @@ bool CVideoPlayer::OpenInputStream()
// find any available external subtitles
std::vector<std::string> filenames;
- if (!URIUtils::IsUPnP(m_item.GetPath()))
+ if (!URIUtils::IsUPnP(m_item.GetPath()) &&
+ !m_item.GetProperty("no-ext-subs-scan").asBoolean(false))
CUtil::ScanForExternalSubtitles(m_item.GetDynPath(), filenames);
// load any subtitles from file item
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp
index 66df0e49c7..2ef7f4d521 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp
@@ -77,7 +77,7 @@ CBaseRenderer* CRendererDRMPRIME::Create(CVideoBuffer* buffer)
if (!plane)
return nullptr;
- if (!plane->SupportsFormatAndModifier(format, modifier))
+ if (!drm->FindVideoPlane(format, modifier))
return nullptr;
return new CRendererDRMPRIME();
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp
index 34d1ab6235..33db29b140 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp
@@ -118,9 +118,10 @@ bool CVideoLayerBridgeDRMPRIME::Map(CVideoBufferDRMPRIME* buffer)
flags = DRM_MODE_FB_MODIFIERS;
// add the video frame FB
- ret = drmModeAddFB2WithModifiers(m_DRM->GetFileDescriptor(), buffer->GetWidth(),
- buffer->GetHeight(), layer->format, handles, pitches, offsets,
- modifier, &buffer->m_fb_id, flags);
+ ret = drmModeAddFB2WithModifiers(m_DRM->GetFileDescriptor(),
+ buffer->GetWidth() + buffer->GetXOffset(),
+ buffer->GetHeight() + buffer->GetYOffset(), layer->format,
+ handles, pitches, offsets, modifier, &buffer->m_fb_id, flags);
if (ret < 0)
{
CLog::Log(LOGERROR, "CVideoLayerBridgeDRMPRIME::{} - failed to add fb {}, ret = {}",
@@ -188,8 +189,8 @@ void CVideoLayerBridgeDRMPRIME::SetVideoPlane(CVideoBufferDRMPRIME* buffer, cons
auto plane = m_DRM->GetVideoPlane();
m_DRM->AddProperty(plane, "FB_ID", buffer->m_fb_id);
m_DRM->AddProperty(plane, "CRTC_ID", m_DRM->GetCrtc()->GetCrtcId());
- m_DRM->AddProperty(plane, "SRC_X", 0);
- m_DRM->AddProperty(plane, "SRC_Y", 0);
+ m_DRM->AddProperty(plane, "SRC_X", buffer->GetXOffset() << 16);
+ m_DRM->AddProperty(plane, "SRC_Y", buffer->GetYOffset() << 16);
m_DRM->AddProperty(plane, "SRC_W", buffer->GetWidth() << 16);
m_DRM->AddProperty(plane, "SRC_H", buffer->GetHeight() << 16);
m_DRM->AddProperty(plane, "CRTC_X", static_cast<int32_t>(destRect.x1) & ~1);
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/ConversionMatrix.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/ConversionMatrix.h
index b2c66a7e73..4f43fc0475 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/ConversionMatrix.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/ConversionMatrix.h
@@ -10,6 +10,7 @@
#include <array>
#include <cmath>
+#include <cstdint>
#include <memory>
extern "C" {
diff --git a/xbmc/dialogs/GUIDialogMediaSource.cpp b/xbmc/dialogs/GUIDialogMediaSource.cpp
index 0afbc2d060..1109157c63 100644
--- a/xbmc/dialogs/GUIDialogMediaSource.cpp
+++ b/xbmc/dialogs/GUIDialogMediaSource.cpp
@@ -36,7 +36,7 @@
#if defined(TARGET_ANDROID)
#include "utils/FileUtils.h"
-#include "platform/android/activity/XBMCApp.h"
+#include "platform/android/storage/AndroidStorageProvider.h"
#endif
#ifdef TARGET_WINDOWS_STORE
@@ -249,7 +249,8 @@ void CGUIDialogMediaSource::OnPathBrowse(int item)
#if defined(TARGET_ANDROID)
// add the default android music directory
std::string path;
- if (CXBMCApp::GetExternalStorage(path, "music") && !path.empty() && CDirectory::Exists(path))
+ if (CAndroidStorageProvider::GetExternalStorage(path, "music") && !path.empty() &&
+ CDirectory::Exists(path))
{
share1.strPath = path;
share1.strName = g_localizeStrings.Get(20240);
@@ -303,7 +304,8 @@ void CGUIDialogMediaSource::OnPathBrowse(int item)
#if defined(TARGET_ANDROID)
// add the default android video directory
std::string path;
- if (CXBMCApp::GetExternalStorage(path, "videos") && !path.empty() && CFileUtils::Exists(path))
+ if (CAndroidStorageProvider::GetExternalStorage(path, "videos") && !path.empty() &&
+ CFileUtils::Exists(path))
{
share1.strPath = path;
share1.strName = g_localizeStrings.Get(20241);
@@ -349,7 +351,8 @@ void CGUIDialogMediaSource::OnPathBrowse(int item)
#if defined(TARGET_ANDROID)
// add the default android music directory
std::string path;
- if (CXBMCApp::GetExternalStorage(path, "pictures") && !path.empty() && CFileUtils::Exists(path))
+ if (CAndroidStorageProvider::GetExternalStorage(path, "pictures") && !path.empty() &&
+ CFileUtils::Exists(path))
{
share1.strPath = path;
share1.strName = g_localizeStrings.Get(20242);
@@ -358,7 +361,8 @@ void CGUIDialogMediaSource::OnPathBrowse(int item)
}
path.clear();
- if (CXBMCApp::GetExternalStorage(path, "photos") && !path.empty() && CFileUtils::Exists(path))
+ if (CAndroidStorageProvider::GetExternalStorage(path, "photos") && !path.empty() &&
+ CFileUtils::Exists(path))
{
share1.strPath = path;
share1.strName = g_localizeStrings.Get(20243);
diff --git a/xbmc/filesystem/DirectoryFactory.cpp b/xbmc/filesystem/DirectoryFactory.cpp
index 465816c4b9..e9c76cba97 100644
--- a/xbmc/filesystem/DirectoryFactory.cpp
+++ b/xbmc/filesystem/DirectoryFactory.cpp
@@ -97,7 +97,14 @@ using namespace XFILE;
*/
IDirectory* CDirectoryFactory::Create(const CFileItem& item)
{
- return Create(CURL{item.GetDynPath()});
+ CURL curl{item.GetDynPath()};
+
+ // Store the mimetype, allowing the PlayListFactory to set it on the created FileItem
+ const std::string& mimeType = item.GetMimeType();
+ if (!mimeType.empty())
+ curl.SetOption("mimetype", mimeType);
+
+ return Create(curl);
}
/*!
diff --git a/xbmc/filesystem/PlaylistFileDirectory.cpp b/xbmc/filesystem/PlaylistFileDirectory.cpp
index d95989067f..18e5d7affa 100644
--- a/xbmc/filesystem/PlaylistFileDirectory.cpp
+++ b/xbmc/filesystem/PlaylistFileDirectory.cpp
@@ -25,12 +25,11 @@ namespace XFILE
bool CPlaylistFileDirectory::GetDirectory(const CURL& url, CFileItemList& items)
{
- const std::string pathToUrl = url.Get();
- std::unique_ptr<PLAYLIST::CPlayList> pPlayList(PLAYLIST::CPlayListFactory::Create(pathToUrl));
+ std::unique_ptr<PLAYLIST::CPlayList> pPlayList(PLAYLIST::CPlayListFactory::Create(url));
if (nullptr != pPlayList)
{
// load it
- if (!pPlayList->Load(pathToUrl))
+ if (!pPlayList->Load(url.Get()))
return false; //hmmm unable to load playlist?
PLAYLIST::CPlayList playlist = *pPlayList;
@@ -47,12 +46,11 @@ namespace XFILE
bool CPlaylistFileDirectory::ContainsFiles(const CURL& url)
{
- const std::string pathToUrl = url.Get();
- std::unique_ptr<PLAYLIST::CPlayList> pPlayList(PLAYLIST::CPlayListFactory::Create(pathToUrl));
+ std::unique_ptr<PLAYLIST::CPlayList> pPlayList(PLAYLIST::CPlayListFactory::Create(url));
if (nullptr != pPlayList)
{
// load it
- if (!pPlayList->Load(pathToUrl))
+ if (!pPlayList->Load(url.Get()))
return false; //hmmm unable to load playlist?
return (pPlayList->size() > 1);
diff --git a/xbmc/guilib/FFmpegImage.h b/xbmc/guilib/FFmpegImage.h
index 0f7cee380c..8d34def513 100644
--- a/xbmc/guilib/FFmpegImage.h
+++ b/xbmc/guilib/FFmpegImage.h
@@ -9,6 +9,8 @@
#pragma once
#include "iimage.h"
+
+#include <cstdint>
#include <memory>
extern "C"
diff --git a/xbmc/guilib/GUIComponent.cpp b/xbmc/guilib/GUIComponent.cpp
index 5c8b414fd8..449a85d073 100644
--- a/xbmc/guilib/GUIComponent.cpp
+++ b/xbmc/guilib/GUIComponent.cpp
@@ -18,6 +18,7 @@
#include "TextureManager.h"
#include "URL.h"
#include "dialogs/GUIDialogYesNo.h"
+#include "handlers/GUIAnnouncementHandlerContainer.h"
#include <memory>
@@ -28,7 +29,8 @@ CGUIComponent::CGUIComponent()
m_stereoscopicsManager(std::make_unique<CStereoscopicsManager>()),
m_guiInfoManager(std::make_unique<CGUIInfoManager>()),
m_guiColorManager(std::make_unique<CGUIColorManager>()),
- m_guiAudioManager(std::make_unique<CGUIAudioManager>())
+ m_guiAudioManager(std::make_unique<CGUIAudioManager>()),
+ m_announcementHandlerContainer(std::make_unique<CGUIAnnouncementHandlerContainer>())
{
}
diff --git a/xbmc/guilib/GUIComponent.h b/xbmc/guilib/GUIComponent.h
index b7eb75c58a..2e3e7aadff 100644
--- a/xbmc/guilib/GUIComponent.h
+++ b/xbmc/guilib/GUIComponent.h
@@ -18,6 +18,7 @@ class CStereoscopicsManager;
class CGUIInfoManager;
class CGUIColorManager;
class CGUIAudioManager;
+class CGUIAnnouncementHandlerContainer;
class CGUIComponent
{
@@ -47,4 +48,5 @@ protected:
std::unique_ptr<CGUIInfoManager> m_guiInfoManager;
std::unique_ptr<CGUIColorManager> m_guiColorManager;
std::unique_ptr<CGUIAudioManager> m_guiAudioManager;
+ std::unique_ptr<CGUIAnnouncementHandlerContainer> m_announcementHandlerContainer;
};
diff --git a/xbmc/guilib/handlers/CMakeLists.txt b/xbmc/guilib/handlers/CMakeLists.txt
new file mode 100644
index 0000000000..fc052e35df
--- /dev/null
+++ b/xbmc/guilib/handlers/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(SOURCES GUIAnnouncementHandlerContainer.cpp
+ sources/GUISourcesAnnouncementHandler.cpp)
+
+set(HEADERS GUIAnnouncementHandlerContainer.h
+ sources/GUISourcesAnnouncementHandler.h)
+
+core_add_library(guilib_announcement_handlers)
diff --git a/xbmc/guilib/handlers/GUIAnnouncementHandlerContainer.cpp b/xbmc/guilib/handlers/GUIAnnouncementHandlerContainer.cpp
new file mode 100644
index 0000000000..f7a5fbae4a
--- /dev/null
+++ b/xbmc/guilib/handlers/GUIAnnouncementHandlerContainer.cpp
@@ -0,0 +1,16 @@
+/*
+ * 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 "GUIAnnouncementHandlerContainer.h"
+
+#include "sources/GUISourcesAnnouncementHandler.h"
+
+CGUIAnnouncementHandlerContainer::CGUIAnnouncementHandlerContainer()
+{
+ m_announcementHandlers.emplace_back(std::make_unique<CGUISourcesAnnouncementHandler>());
+}
diff --git a/xbmc/guilib/handlers/GUIAnnouncementHandlerContainer.h b/xbmc/guilib/handlers/GUIAnnouncementHandlerContainer.h
new file mode 100644
index 0000000000..40122c5dbb
--- /dev/null
+++ b/xbmc/guilib/handlers/GUIAnnouncementHandlerContainer.h
@@ -0,0 +1,29 @@
+/*
+ * 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 "interfaces/IAnnouncer.h"
+
+#include <memory>
+#include <vector>
+
+/*!
+\brief This class is a container of announcement handlers per application component. It allows the GUI Layer
+to execute GUI Actions upon receiving announcements from other components effectively decoupling GUI
+from other components.
+*/
+class CGUIAnnouncementHandlerContainer final
+{
+public:
+ CGUIAnnouncementHandlerContainer();
+ ~CGUIAnnouncementHandlerContainer() = default;
+
+private:
+ std::vector<std::unique_ptr<ANNOUNCEMENT::IAnnouncer>> m_announcementHandlers;
+};
diff --git a/xbmc/guilib/handlers/sources/GUISourcesAnnouncementHandler.cpp b/xbmc/guilib/handlers/sources/GUISourcesAnnouncementHandler.cpp
new file mode 100644
index 0000000000..251f0e14ec
--- /dev/null
+++ b/xbmc/guilib/handlers/sources/GUISourcesAnnouncementHandler.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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 "GUISourcesAnnouncementHandler.h"
+
+#include "GUIUserMessages.h"
+#include "ServiceBroker.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "interfaces/AnnouncementManager.h"
+
+CGUISourcesAnnouncementHandler::CGUISourcesAnnouncementHandler()
+{
+ CServiceBroker::GetAnnouncementManager()->AddAnnouncer(this);
+}
+
+CGUISourcesAnnouncementHandler::~CGUISourcesAnnouncementHandler()
+{
+ CServiceBroker::GetAnnouncementManager()->RemoveAnnouncer(this);
+}
+
+void CGUISourcesAnnouncementHandler::Announce(ANNOUNCEMENT::AnnouncementFlag flag,
+ const std::string& sender,
+ const std::string& message,
+ const CVariant& data)
+{
+ // We are only interested in sources changes
+ if ((flag & ANNOUNCEMENT::Sources) == 0)
+ return;
+
+ if (message == "OnAdded" || message == "OnRemoved" || message == "OnUpdated")
+ {
+ CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
+ message.SetStringParam(data.asString());
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message);
+ }
+}
diff --git a/xbmc/guilib/handlers/sources/GUISourcesAnnouncementHandler.h b/xbmc/guilib/handlers/sources/GUISourcesAnnouncementHandler.h
new file mode 100644
index 0000000000..0ec166fdf1
--- /dev/null
+++ b/xbmc/guilib/handlers/sources/GUISourcesAnnouncementHandler.h
@@ -0,0 +1,26 @@
+/*
+ * 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 "interfaces/IAnnouncer.h"
+
+/*!
+\brief Handler for announcements of type sources
+*/
+class CGUISourcesAnnouncementHandler : public ANNOUNCEMENT::IAnnouncer
+{
+public:
+ CGUISourcesAnnouncementHandler();
+ ~CGUISourcesAnnouncementHandler();
+
+ void Announce(ANNOUNCEMENT::AnnouncementFlag flag,
+ const std::string& sender,
+ const std::string& message,
+ const CVariant& data) override;
+};
diff --git a/xbmc/input/keymaps/remote/IRTranslator.h b/xbmc/input/keymaps/remote/IRTranslator.h
index 96eddcf153..862fb7599c 100644
--- a/xbmc/input/keymaps/remote/IRTranslator.h
+++ b/xbmc/input/keymaps/remote/IRTranslator.h
@@ -8,6 +8,7 @@
#pragma once
+#include <cstdint>
#include <map>
#include <memory>
#include <string>
diff --git a/xbmc/interfaces/IAnnouncer.h b/xbmc/interfaces/IAnnouncer.h
index 7c20203573..513fb25937 100644
--- a/xbmc/interfaces/IAnnouncer.h
+++ b/xbmc/interfaces/IAnnouncer.h
@@ -13,33 +13,35 @@
class CVariant;
namespace ANNOUNCEMENT
{
- enum AnnouncementFlag
- {
- Player = 0x001,
- Playlist = 0x002,
- GUI = 0x004,
- System = 0x008,
- VideoLibrary = 0x010,
- AudioLibrary = 0x020,
- Application = 0x040,
- Input = 0x080,
- PVR = 0x100,
- Other = 0x200,
- Info = 0x400
- };
+enum AnnouncementFlag
+{
+ Player = 0x001,
+ Playlist = 0x002,
+ GUI = 0x004,
+ System = 0x008,
+ VideoLibrary = 0x010,
+ AudioLibrary = 0x020,
+ Application = 0x040,
+ Input = 0x080,
+ PVR = 0x100,
+ Other = 0x200,
+ Info = 0x400,
+ Sources = 0x800
+};
- const auto ANNOUNCE_ALL = (Player | Playlist | GUI | System | VideoLibrary | AudioLibrary | Application | Input | ANNOUNCEMENT::PVR | Other);
+const auto ANNOUNCE_ALL = (Player | Playlist | GUI | System | VideoLibrary | AudioLibrary |
+ Application | Input | ANNOUNCEMENT::PVR | Other);
- /*!
+/*!
\brief Returns a string representation for the
given AnnouncementFlag
\param notification Specific AnnouncementFlag
\return String representation of the given AnnouncementFlag
*/
- inline const char *AnnouncementFlagToString(const AnnouncementFlag &notification)
+inline const char* AnnouncementFlagToString(const AnnouncementFlag& notification)
+{
+ switch (notification)
{
- switch (notification)
- {
case Player:
return "Player";
case Playlist:
@@ -62,10 +64,12 @@ namespace ANNOUNCEMENT
return "Other";
case Info:
return "Info";
+ case Sources:
+ return "Sources";
default:
return "Unknown";
- }
}
+}
class IAnnouncer
{
diff --git a/xbmc/messaging/ThreadMessage.h b/xbmc/messaging/ThreadMessage.h
index 1a277ffcd4..8360d30cc1 100644
--- a/xbmc/messaging/ThreadMessage.h
+++ b/xbmc/messaging/ThreadMessage.h
@@ -8,6 +8,7 @@
#pragma once
+#include <cstdint>
#include <memory>
#include <string>
#include <utility>
diff --git a/xbmc/network/ZeroconfBrowser.h b/xbmc/network/ZeroconfBrowser.h
index 76a4439a11..7f104eabc5 100644
--- a/xbmc/network/ZeroconfBrowser.h
+++ b/xbmc/network/ZeroconfBrowser.h
@@ -89,8 +89,7 @@ public:
void Stop();
///returns the list of found services
- /// if this is updated, the following message with "zeroconf://" as path is sent:
- /// CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
+ /// if this is updated, a source update announcement with "zeroconf://" as path is sent:
std::vector<ZeroconfService> GetFoundServices();
///@}
diff --git a/xbmc/network/mdns/ZeroconfBrowserMDNS.cpp b/xbmc/network/mdns/ZeroconfBrowserMDNS.cpp
index c4a1c1ecab..9546dcc6b5 100644
--- a/xbmc/network/mdns/ZeroconfBrowserMDNS.cpp
+++ b/xbmc/network/mdns/ZeroconfBrowserMDNS.cpp
@@ -8,11 +8,8 @@
#include "ZeroconfBrowserMDNS.h"
-#include "GUIUserMessages.h"
#include "ServiceBroker.h"
-#include "guilib/GUIComponent.h"
-#include "guilib/GUIMessage.h"
-#include "guilib/GUIWindowManager.h"
+#include "interfaces/AnnouncementManager.h"
#include "network/DNSNameCache.h"
#include "utils/log.h"
@@ -88,10 +85,11 @@ void DNSSD_API CZeroconfBrowserMDNS::BrowserCallback(DNSServiceRef browser,
}
if(! (flags & kDNSServiceFlagsMoreComing) )
{
- CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
- message.SetStringParam("zeroconf://");
- CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message);
- CLog::Log(LOGDEBUG, "ZeroconfBrowserMDNS::BrowserCallback sent gui update for path zeroconf://");
+ CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Sources, "OnUpdated",
+ CVariant{"zeroconf://"});
+ CLog::Log(
+ LOGDEBUG,
+ "ZeroconfBrowserMDNS::BrowserCallback sent source update announce for path zeroconf://");
}
}
else
diff --git a/xbmc/network/upnp/UPnP.cpp b/xbmc/network/upnp/UPnP.cpp
index 2acfc55069..371efbace2 100644
--- a/xbmc/network/upnp/UPnP.cpp
+++ b/xbmc/network/upnp/UPnP.cpp
@@ -13,7 +13,6 @@
#include "UPnP.h"
#include "FileItem.h"
-#include "GUIUserMessages.h"
#include "ServiceBroker.h"
#include "UPnPInternal.h"
#include "UPnPRenderer.h"
@@ -21,8 +20,7 @@
#include "UPnPSettings.h"
#include "URL.h"
#include "cores/playercorefactory/PlayerCoreFactory.h"
-#include "guilib/GUIComponent.h"
-#include "guilib/GUIWindowManager.h"
+#include "interfaces/AnnouncementManager.h"
#include "messaging/ApplicationMessenger.h"
#include "network/Network.h"
#include "profiles/ProfileManager.h"
@@ -171,19 +169,15 @@ public:
// PLT_MediaBrowser methods
bool OnMSAdded(PLT_DeviceDataReference& device) override
{
- CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
- message.SetStringParam("upnp://");
- CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message);
+ CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Sources, "OnAdded",
+ CVariant{"upnp://"});
return PLT_SyncMediaBrowser::OnMSAdded(device);
}
void OnMSRemoved(PLT_DeviceDataReference& device) override
{
- PLT_SyncMediaBrowser::OnMSRemoved(device);
-
- CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
- message.SetStringParam("upnp://");
- CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message);
+ CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Sources, "OnRemoved",
+ CVariant{"upnp://"});
PLT_SyncMediaBrowser::OnMSRemoved(device);
}
@@ -202,9 +196,8 @@ public:
}
m_logger->debug("notified container update {}", (const char*)path);
- CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
- message.SetStringParam(path.GetChars());
- CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message);
+ CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Sources, "OnUpdated",
+ CVariant{path.GetChars()});
}
bool MarkWatched(const CFileItem& item, const bool watched)
diff --git a/xbmc/network/upnp/UPnPRenderer.cpp b/xbmc/network/upnp/UPnPRenderer.cpp
index acf6296d3b..196824fbee 100644
--- a/xbmc/network/upnp/UPnPRenderer.cpp
+++ b/xbmc/network/upnp/UPnPRenderer.cpp
@@ -686,6 +686,7 @@ NPT_Result CUPnPRenderer::PlayMedia(const NPT_String& uri,
}
else
{
+ item->SetProperty("no-ext-subs-scan", true);
CFileItemList* l = new CFileItemList; //don't delete,
l->Add(std::make_shared<CFileItem>(*item));
CServiceBroker::GetAppMessenger()->PostMsg(TMSG_MEDIA_PLAY, -1, -1, static_cast<void*>(l));
diff --git a/xbmc/platform/android/PlatformAndroid.cpp b/xbmc/platform/android/PlatformAndroid.cpp
index ba9208f6f5..d35896cd14 100644
--- a/xbmc/platform/android/PlatformAndroid.cpp
+++ b/xbmc/platform/android/PlatformAndroid.cpp
@@ -17,6 +17,7 @@
#include "platform/android/activity/XBMCApp.h"
#include "platform/android/powermanagement/AndroidPowerSyscall.h"
+#include "platform/android/storage/AndroidStorageProvider.h"
#include <stdlib.h>
@@ -66,7 +67,7 @@ void CPlatformAndroid::PlatformSyslog()
CJNIBuild::BRAND, CJNIBuild::MODEL, CJNIBuild::HARDWARE);
std::string extstorage;
- bool extready = CXBMCApp::GetExternalStorage(extstorage);
+ const bool extready = CAndroidStorageProvider::GetExternalStorage(extstorage);
CLog::Log(
LOGINFO, "External storage path = {}; status = {}; Permissions = {}{}", extstorage,
extready ? "ok" : "nok",
diff --git a/xbmc/platform/android/activity/XBMCApp.cpp b/xbmc/platform/android/activity/XBMCApp.cpp
index b4cdde669c..10e00d0146 100644
--- a/xbmc/platform/android/activity/XBMCApp.cpp
+++ b/xbmc/platform/android/activity/XBMCApp.cpp
@@ -81,7 +81,6 @@
#include <androidjni/Cursor.h>
#include <androidjni/Display.h>
#include <androidjni/DisplayManager.h>
-#include <androidjni/Environment.h>
#include <androidjni/File.h>
#include <androidjni/Intent.h>
#include <androidjni/IntentFilter.h>
@@ -1091,42 +1090,6 @@ int CXBMCApp::GetBatteryLevel() const
return m_batteryLevel;
}
-bool CXBMCApp::GetExternalStorage(std::string &path, const std::string &type /* = "" */)
-{
- std::string sType;
- std::string mountedState;
- bool mounted = false;
-
- if(type == "files" || type.empty())
- {
- CJNIFile external = CJNIEnvironment::getExternalStorageDirectory();
- if (external)
- path = external.getAbsolutePath();
- }
- else
- {
- if (type == "music")
- sType = "Music"; // Environment.DIRECTORY_MUSIC
- else if (type == "videos")
- sType = "Movies"; // Environment.DIRECTORY_MOVIES
- else if (type == "pictures")
- sType = "Pictures"; // Environment.DIRECTORY_PICTURES
- else if (type == "photos")
- sType = "DCIM"; // Environment.DIRECTORY_DCIM
- else if (type == "downloads")
- sType = "Download"; // Environment.DIRECTORY_DOWNLOADS
- if (!sType.empty())
- {
- CJNIFile external = CJNIEnvironment::getExternalStoragePublicDirectory(sType);
- if (external)
- path = external.getAbsolutePath();
- }
- }
- mountedState = CJNIEnvironment::getExternalStorageState();
- mounted = (mountedState == "mounted" || mountedState == "mounted_ro");
- return mounted && !path.empty();
-}
-
// Used in Application.cpp to figure out volume steps
int CXBMCApp::GetMaxSystemVolume()
{
diff --git a/xbmc/platform/android/activity/XBMCApp.h b/xbmc/platform/android/activity/XBMCApp.h
index 6fa89cbce3..73f5dcdf09 100644
--- a/xbmc/platform/android/activity/XBMCApp.h
+++ b/xbmc/platform/android/activity/XBMCApp.h
@@ -166,13 +166,6 @@ public:
const std::string& className = std::string());
std::vector<androidPackage> GetApplications() const;
- /*!
- * \brief If external storage is available, it returns the path for the external storage (for the specified type)
- * \param path will contain the path of the external storage (for the specified type)
- * \param type optional type. Possible values are "", "files", "music", "videos", "pictures", "photos, "downloads"
- * \return true if external storage is available and a valid path has been stored in the path parameter
- */
- static bool GetExternalStorage(std::string& path, const std::string& type = "");
static int GetMaxSystemVolume();
static float GetSystemVolume();
static void SetSystemVolume(float percent);
diff --git a/xbmc/platform/android/network/ZeroconfBrowserAndroid.cpp b/xbmc/platform/android/network/ZeroconfBrowserAndroid.cpp
index dd6db2576b..d31564f5ea 100644
--- a/xbmc/platform/android/network/ZeroconfBrowserAndroid.cpp
+++ b/xbmc/platform/android/network/ZeroconfBrowserAndroid.cpp
@@ -8,11 +8,8 @@
#include "ZeroconfBrowserAndroid.h"
-#include "GUIUserMessages.h"
#include "ServiceBroker.h"
-#include "guilib/GUIComponent.h"
-#include "guilib/GUIMessage.h"
-#include "guilib/GUIWindowManager.h"
+#include "interfaces/AnnouncementManager.h"
#include "network/DNSNameCache.h"
#include "utils/log.h"
@@ -241,10 +238,10 @@ void CZeroconfBrowserAndroidDiscover::onServiceFound(const jni::CJNINsdServiceIn
s.GetName(), s.GetType(), s.GetDomain());
m_browser->addDiscoveredService(this, s);
- CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
- message.SetStringParam("zeroconf://");
- CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message);
- CLog::Log(LOGDEBUG, "CZeroconfBrowserAndroidDiscover::onServiceFound sent gui update for path zeroconf://");
+ CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Sources, "OnUpdated",
+ CVariant{"zeroconf://"});
+ CLog::Log(LOGDEBUG, "CZeroconfBrowserAndroidDiscover::onServiceFound sent source update announce "
+ "for path zeroconf://");
}
void CZeroconfBrowserAndroidDiscover::onServiceLost(const jni::CJNINsdServiceInfo& serviceInfo)
diff --git a/xbmc/platform/android/storage/AndroidStorageProvider.cpp b/xbmc/platform/android/storage/AndroidStorageProvider.cpp
index 33f7ab8a23..59fe3d6ae2 100644
--- a/xbmc/platform/android/storage/AndroidStorageProvider.cpp
+++ b/xbmc/platform/android/storage/AndroidStorageProvider.cpp
@@ -17,8 +17,6 @@
#include "utils/URIUtils.h"
#include "utils/log.h"
-#include "platform/android/activity/XBMCApp.h"
-
#include <array>
#include <cstdio>
#include <cstdlib>
@@ -131,7 +129,7 @@ void CAndroidStorageProvider::GetLocalDrives(VECSOURCES &localDrives)
// external directory
std::string path;
- if (CXBMCApp::GetExternalStorage(path) && !path.empty() && XFILE::CDirectory::Exists(path))
+ if (GetExternalStorage(path) && !path.empty() && XFILE::CDirectory::Exists(path))
{
share.strPath = path;
share.strName = g_localizeStrings.Get(21456);
@@ -391,8 +389,7 @@ std::vector<std::string> CAndroidStorageProvider::GetDiskUsage()
usage.clear();
// add external storage if available
std::string path;
- if (CXBMCApp::GetExternalStorage(path) && !path.empty() && GetStorageUsage(path, usage) &&
- !usage.empty())
+ if (GetExternalStorage(path) && !path.empty() && GetStorageUsage(path, usage) && !usage.empty())
result.push_back(usage);
// add removable storage
@@ -451,3 +448,41 @@ bool CAndroidStorageProvider::GetStorageUsage(const std::string& path, std::stri
PATH_MAXLEN, totalSize, "G", usedSize, "G", freeSize, "G", usedPercentage, "%");
return true;
}
+
+bool CAndroidStorageProvider::GetExternalStorage(std::string& path,
+ const std::string& type /* = "" */)
+{
+ std::string sType;
+ std::string mountedState;
+ bool mounted = false;
+
+ if (type == "files" || type.empty())
+ {
+ CJNIFile external = CJNIEnvironment::getExternalStorageDirectory();
+ if (external)
+ path = external.getAbsolutePath();
+ }
+ else
+ {
+ if (type == "music")
+ sType = "Music"; // Environment.DIRECTORY_MUSIC
+ else if (type == "videos")
+ sType = "Movies"; // Environment.DIRECTORY_MOVIES
+ else if (type == "pictures")
+ sType = "Pictures"; // Environment.DIRECTORY_PICTURES
+ else if (type == "photos")
+ sType = "DCIM"; // Environment.DIRECTORY_DCIM
+ else if (type == "downloads")
+ sType = "Download"; // Environment.DIRECTORY_DOWNLOADS
+ if (!sType.empty())
+ {
+ CJNIFile external = CJNIEnvironment::getExternalStoragePublicDirectory(sType);
+ if (external)
+ path = external.getAbsolutePath();
+ }
+ }
+
+ mountedState = CJNIEnvironment::getExternalStorageState();
+ mounted = (mountedState == "mounted" || mountedState == "mounted_ro");
+ return mounted && !path.empty();
+}
diff --git a/xbmc/platform/android/storage/AndroidStorageProvider.h b/xbmc/platform/android/storage/AndroidStorageProvider.h
index e39ff60dea..abd7b8e3b2 100644
--- a/xbmc/platform/android/storage/AndroidStorageProvider.h
+++ b/xbmc/platform/android/storage/AndroidStorageProvider.h
@@ -30,6 +30,14 @@ public:
bool PumpDriveChangeEvents(IStorageEventsCallback* callback) override;
+ /*!
+ * \brief If external storage is available, it returns the path for the external storage (for the specified type)
+ * \param path will contain the path of the external storage (for the specified type)
+ * \param type optional type. Possible values are "", "files", "music", "videos", "pictures", "photos, "downloads"
+ * \return true if external storage is available and a valid path has been stored in the path parameter
+ */
+ static bool GetExternalStorage(std::string& path, const std::string& type = "");
+
private:
std::string unescape(const std::string& str);
VECSOURCES m_removableDrives;
diff --git a/xbmc/platform/darwin/network/ZeroconfBrowserDarwin.cpp b/xbmc/platform/darwin/network/ZeroconfBrowserDarwin.cpp
index 50515d0879..e2078a3520 100644
--- a/xbmc/platform/darwin/network/ZeroconfBrowserDarwin.cpp
+++ b/xbmc/platform/darwin/network/ZeroconfBrowserDarwin.cpp
@@ -8,11 +8,8 @@
#include "ZeroconfBrowserDarwin.h"
-#include "GUIUserMessages.h"
#include "ServiceBroker.h"
-#include "guilib/GUIComponent.h"
-#include "guilib/GUIMessage.h"
-#include "guilib/GUIWindowManager.h"
+#include "interfaces/AnnouncementManager.h"
#include "utils/log.h"
#include "platform/darwin/DarwinUtils.h"
@@ -168,10 +165,10 @@ void CZeroconfBrowserDarwin::BrowserCallback(CFNetServiceBrowserRef browser, CFO
}
if (! (flags & kCFNetServiceFlagMoreComing) )
{
- CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
- message.SetStringParam("zeroconf://");
- CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message);
- CLog::Log(LOGDEBUG, "CZeroconfBrowserDarwin::BrowserCallback sent gui update for path zeroconf://");
+ CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Sources, "OnUpdated",
+ CVariant{"zeroconf://"});
+ CLog::Log(LOGDEBUG, "CZeroconfBrowserDarwin::BrowserCallback sent sources update "
+ "announcement for path zeroconf://");
}
} else
{
diff --git a/xbmc/platform/linux/storage/UDevProvider.cpp b/xbmc/platform/linux/storage/UDevProvider.cpp
index 7123e87a77..df5b9844c5 100644
--- a/xbmc/platform/linux/storage/UDevProvider.cpp
+++ b/xbmc/platform/linux/storage/UDevProvider.cpp
@@ -17,7 +17,9 @@ extern "C" {
#include <poll.h>
}
-static const char *get_mountpoint(const char *devnode)
+namespace
+{
+const char* get_mountpoint(const char* devnode)
{
static char buf[4096];
const char *delim = " ";
@@ -59,6 +61,7 @@ static const char *get_mountpoint(const char *devnode)
fclose(fp);
return mountpoint;
}
+} // namespace
CUDevProvider::CUDevProvider()
{
diff --git a/xbmc/playlists/PlayListFactory.cpp b/xbmc/playlists/PlayListFactory.cpp
index 7fe5ff6fcb..63b9bd401d 100644
--- a/xbmc/playlists/PlayListFactory.cpp
+++ b/xbmc/playlists/PlayListFactory.cpp
@@ -9,6 +9,7 @@
#include "PlayListFactory.h"
#include "FileItem.h"
+#include "URL.h"
#include "network/NetworkFileItemClassify.h"
#include "playlists/PlayListASX.h"
#include "playlists/PlayListB4S.h"
@@ -25,6 +26,19 @@
namespace KODI::PLAYLIST
{
+CPlayList* CPlayListFactory::Create(const CURL& url)
+{
+ CFileItem item{url.Get(), false};
+
+ if (url.HasOption("mimetype"))
+ {
+ item.SetContentLookup(false);
+ item.SetMimeType(url.GetOption("mimetype"));
+ }
+
+ return Create(item);
+}
+
CPlayList* CPlayListFactory::Create(const std::string& filename)
{
CFileItem item(filename,false);
diff --git a/xbmc/playlists/PlayListFactory.h b/xbmc/playlists/PlayListFactory.h
index 5161150ea5..410c1e392d 100644
--- a/xbmc/playlists/PlayListFactory.h
+++ b/xbmc/playlists/PlayListFactory.h
@@ -20,6 +20,7 @@ namespace KODI::PLAYLIST
class CPlayListFactory
{
public:
+ static CPlayList* Create(const CURL& url);
static CPlayList* Create(const std::string& filename);
static CPlayList* Create(const CFileItem& item);
static bool IsPlaylist(const CURL& url);
diff --git a/xbmc/pvr/PVRContextMenus.cpp b/xbmc/pvr/PVRContextMenus.cpp
index f882c9e624..9faa27d1e8 100644
--- a/xbmc/pvr/PVRContextMenus.cpp
+++ b/xbmc/pvr/PVRContextMenus.cpp
@@ -268,53 +268,37 @@ bool FindSimilar::Execute(const CFileItemPtr& item) const
bool StartRecording::IsVisible(const CFileItem& item) const
{
- const std::shared_ptr<const CPVRClient> client = CServiceBroker::GetPVRManager().GetClient(item);
-
- std::shared_ptr<CPVRChannel> channel = item.GetPVRChannelInfoTag();
+ const std::shared_ptr<CPVRChannel> channel{item.GetPVRChannelInfoTag()};
if (channel)
+ {
+ const std::shared_ptr<const CPVRClient> client{CServiceBroker::GetPVRManager().GetClient(item)};
return client && client->GetClientCapabilities().SupportsTimers() &&
!CServiceBroker::GetPVRManager().Timers()->IsRecordingOnChannel(*channel);
+ }
- const std::shared_ptr<const CPVREpgInfoTag> epg = item.GetEPGInfoTag();
- if (epg && epg->IsRecordable())
+ const std::shared_ptr<const CPVREpgInfoTag> epgTag{item.GetEPGInfoTag()};
+ if (epgTag && epgTag->IsRecordable())
{
- if (epg->IsGapTag())
- {
- channel = CServiceBroker::GetPVRManager().ChannelGroups()->GetChannelForEpgTag(epg);
- if (channel)
- {
- return client && client->GetClientCapabilities().SupportsTimers() &&
- !CServiceBroker::GetPVRManager().Timers()->IsRecordingOnChannel(*channel);
- }
- }
- else
- {
- return client && client->GetClientCapabilities().SupportsTimers() &&
- !CServiceBroker::GetPVRManager().Timers()->GetTimerForEpgTag(epg);
- }
+ const std::shared_ptr<const CPVRClient> client{CServiceBroker::GetPVRManager().GetClient(item)};
+ return client && client->GetClientCapabilities().SupportsTimers() &&
+ !CServiceBroker::GetPVRManager().Timers()->GetTimerForEpgTag(epgTag);
}
+
return false;
}
bool StartRecording::Execute(const CFileItemPtr& item) const
{
- const std::shared_ptr<const CPVREpgInfoTag> epgTag = item->GetEPGInfoTag();
- if (!epgTag || epgTag->IsActive())
- {
- // instant recording
- std::shared_ptr<CPVRChannel> channel;
- if (epgTag)
- channel = CServiceBroker::GetPVRManager().ChannelGroups()->GetChannelForEpgTag(epgTag);
+ const std::shared_ptr<CPVRChannel> channel{item->GetPVRChannelInfoTag()};
+ if (channel)
+ return CServiceBroker::GetPVRManager().Get<PVR::GUI::Timers>().SetRecordingOnChannel(channel,
+ true);
- if (!channel)
- channel = item->GetPVRChannelInfoTag();
+ const std::shared_ptr<const CPVREpgInfoTag> epgTag{item->GetEPGInfoTag()};
+ if (epgTag)
+ return CServiceBroker::GetPVRManager().Get<PVR::GUI::Timers>().AddTimer(*item, false);
- if (channel)
- return CServiceBroker::GetPVRManager().Get<PVR::GUI::Timers>().SetRecordingOnChannel(channel,
- true);
- }
-
- return CServiceBroker::GetPVRManager().Get<PVR::GUI::Timers>().AddTimer(*item, false);
+ return false;
}
///////////////////////////////////////////////////////////////////////////////
@@ -337,9 +321,13 @@ bool StopRecording::IsVisible(const CFileItem& item) const
const std::shared_ptr<const CPVREpgInfoTag> epg = item.GetEPGInfoTag();
if (epg && epg->IsGapTag())
{
- channel = CServiceBroker::GetPVRManager().ChannelGroups()->GetChannelForEpgTag(epg);
- if (channel)
- return CServiceBroker::GetPVRManager().Timers()->IsRecordingOnChannel(*channel);
+ const CDateTime now{CDateTime::GetUTCDateTime()};
+ if (epg->StartAsUTC() <= now && epg->EndAsUTC() >= now)
+ {
+ channel = CServiceBroker::GetPVRManager().ChannelGroups()->GetChannelForEpgTag(epg);
+ if (channel)
+ return CServiceBroker::GetPVRManager().Timers()->IsRecordingOnChannel(*channel);
+ }
}
return false;
@@ -350,12 +338,16 @@ bool StopRecording::Execute(const CFileItemPtr& item) const
const std::shared_ptr<const CPVREpgInfoTag> epgTag = item->GetEPGInfoTag();
if (epgTag && epgTag->IsGapTag())
{
- // instance recording
- const std::shared_ptr<CPVRChannel> channel =
- CServiceBroker::GetPVRManager().ChannelGroups()->GetChannelForEpgTag(epgTag);
- if (channel)
- return CServiceBroker::GetPVRManager().Get<PVR::GUI::Timers>().SetRecordingOnChannel(channel,
- false);
+ const CDateTime now{CDateTime::GetUTCDateTime()};
+ if (epgTag->StartAsUTC() <= now && epgTag->EndAsUTC() >= now)
+ {
+ const std::shared_ptr<CPVRChannel> channel{
+ CServiceBroker::GetPVRManager().ChannelGroups()->GetChannelForEpgTag(epgTag)};
+ if (channel)
+ return CServiceBroker::GetPVRManager().Get<PVR::GUI::Timers>().SetRecordingOnChannel(
+ channel, false);
+ }
+ return false;
}
return CServiceBroker::GetPVRManager().Get<PVR::GUI::Timers>().StopRecording(*item);
diff --git a/xbmc/pvr/epg/Epg.cpp b/xbmc/pvr/epg/Epg.cpp
index d1c39edcd3..8bc6045d20 100644
--- a/xbmc/pvr/epg/Epg.cpp
+++ b/xbmc/pvr/epg/Epg.cpp
@@ -223,7 +223,8 @@ bool CPVREpg::UpdateEntry(const std::shared_ptr<CPVREpgInfoTag>& tag, EPG_EVENT_
}
else
{
- if (IsTagExpired(existingTag))
+ // Delete future events and past events if they are older than epg linger time setting
+ if ((existingTag->StartAsUTC() > CDateTime::GetUTCDateTime()) || IsTagExpired(existingTag))
{
m_tags.DeleteEntry(existingTag);
}
diff --git a/xbmc/pvr/filesystem/PVRGUIDirectory.cpp b/xbmc/pvr/filesystem/PVRGUIDirectory.cpp
index d53e8279a9..1fadc5d6d2 100644
--- a/xbmc/pvr/filesystem/PVRGUIDirectory.cpp
+++ b/xbmc/pvr/filesystem/PVRGUIDirectory.cpp
@@ -429,6 +429,54 @@ void GetGetRecordingsSubDirectories(const CPVRRecordingsPath& recParentPath,
} // unnamed namespace
+bool CPVRGUIDirectory::GetRecordingsDirectoryInfo(CFileItem& item)
+{
+ CFileItemList results;
+ const CPVRGUIDirectory dir{item.GetPath()};
+ if (dir.GetRecordingsDirectory(results))
+ {
+ item.SetLabelPreformatted(true);
+ item.SetProperty("totalepisodes", 0);
+ item.SetProperty("watchedepisodes", 0);
+ item.SetProperty("unwatchedepisodes", 0);
+ item.SetProperty("inprogressepisodes", 0);
+
+ int64_t sizeInBytes{0};
+
+ for (const auto& result : results.GetList())
+ {
+ const auto recording{result->GetPVRRecordingInfoTag()};
+ if (!recording)
+ continue;
+
+ if (item.m_dateTime.IsValid() || (item.m_dateTime < recording->RecordingTimeAsLocalTime()))
+ item.m_dateTime = recording->RecordingTimeAsLocalTime();
+
+ item.IncrementProperty("totalepisodes", 1);
+
+ if (recording->GetPlayCount() == 0)
+ item.IncrementProperty("unwatchedepisodes", 1);
+ else
+ item.IncrementProperty("watchedepisodes", 1);
+
+ if (recording->GetResumePoint().IsPartWay())
+ item.IncrementProperty("inprogressepisodes", 1);
+
+ sizeInBytes += recording->GetSizeInBytes();
+ }
+
+ item.SetProperty("recordingsize", StringUtils::SizeToString(sizeInBytes));
+
+ if (item.GetProperty("unwatchedepisodes").asInteger() > 0)
+ item.SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED);
+ else
+ item.SetOverlayImage(CGUIListItem::ICON_OVERLAY_WATCHED);
+
+ return true;
+ }
+ return false;
+}
+
bool CPVRGUIDirectory::GetRecordingsDirectory(CFileItemList& results) const
{
results.SetContent("recordings");
diff --git a/xbmc/pvr/filesystem/PVRGUIDirectory.h b/xbmc/pvr/filesystem/PVRGUIDirectory.h
index 132b0a227d..925d97d0b3 100644
--- a/xbmc/pvr/filesystem/PVRGUIDirectory.h
+++ b/xbmc/pvr/filesystem/PVRGUIDirectory.h
@@ -12,6 +12,7 @@
#include <string>
+class CFileItem;
class CFileItemList;
namespace PVR
@@ -103,6 +104,13 @@ public:
*/
bool GetProvidersDirectory(CFileItemList& results) const;
+ /*!
+ * @brief Get info for a recording folder.
+ * @param item The folder.
+ * @return True on success, false otherwise..
+ */
+ static bool GetRecordingsDirectoryInfo(CFileItem& item);
+
private:
bool GetTimersDirectory(CFileItemList& results) const;
bool GetRecordingsDirectory(CFileItemList& results) const;
diff --git a/xbmc/pvr/guilib/PVRGUIActionsTimers.cpp b/xbmc/pvr/guilib/PVRGUIActionsTimers.cpp
index 570249b12a..a247d46ec5 100644
--- a/xbmc/pvr/guilib/PVRGUIActionsTimers.cpp
+++ b/xbmc/pvr/guilib/PVRGUIActionsTimers.cpp
@@ -207,11 +207,17 @@ bool CPVRGUIActionsTimers::AddTimer(const CFileItem& item,
ParentalCheckResult::SUCCESS)
return false;
+ CDateTime gapStart;
+ int gapDuration{CPVRTimerInfoTag::DEFAULT_PVRRECORD_INSTANTRECORDTIME};
std::shared_ptr<CPVREpgInfoTag> epgTag = CPVRItem(item).GetEpgInfoTag();
if (epgTag)
{
if (epgTag->IsGapTag())
- epgTag.reset(); // for gap tags, we can only create instant timers
+ {
+ gapStart = epgTag->StartAsUTC();
+ gapDuration = (epgTag->EndAsUTC() - gapStart).GetSecondsTotal();
+ epgTag.reset(); // for gap tags, we can only create instant or time-based timers
+ }
}
else if (bCreateRule)
{
@@ -232,9 +238,28 @@ bool CPVRGUIActionsTimers::AddTimer(const CFileItem& item,
return false;
}
- std::shared_ptr<CPVRTimerInfoTag> newTimer(
- epgTag ? CPVRTimerInfoTag::CreateFromEpg(epgTag, bCreateRule)
- : CPVRTimerInfoTag::CreateInstantTimerTag(channel));
+ std::shared_ptr<CPVRTimerInfoTag> newTimer;
+ if (epgTag)
+ {
+ newTimer = CPVRTimerInfoTag::CreateFromEpg(epgTag, bCreateRule);
+ }
+ else if (gapStart.IsValid() &&
+ gapDuration != CPVRTimerInfoTag::DEFAULT_PVRRECORD_INSTANTRECORDTIME)
+ {
+ if (gapStart <= CDateTime::GetUTCDateTime())
+ gapStart = CDateTime{time_t{0}}; // special PVR addon API value for an instant recording
+
+ // prevent super long recordings for channels without any epg data
+ gapDuration = std::min(
+ m_settings.GetIntValue(CSettings::SETTING_PVRRECORD_INSTANTRECORDTIME) * 60, gapDuration);
+
+ newTimer = CPVRTimerInfoTag::CreateTimerTag(channel, gapStart, gapDuration);
+ }
+ else
+ {
+ newTimer = CPVRTimerInfoTag::CreateInstantTimerTag(channel);
+ }
+
if (!newTimer)
{
if (bCreateRule && bFallbackToOneShotTimer)
@@ -562,7 +587,7 @@ bool CPVRGUIActionsTimers::SetRecordingOnChannel(const std::shared_ptr<CPVRChann
const std::shared_ptr<CPVRTimerInfoTag> newTimer(
epgTag ? CPVRTimerInfoTag::CreateFromEpg(epgTag, false)
- : CPVRTimerInfoTag::CreateInstantTimerTag(channel, iDuration));
+ : CPVRTimerInfoTag::CreateInstantTimerTag(channel, iDuration * 60));
if (newTimer)
bReturn = CServiceBroker::GetPVRManager().Timers()->AddTimer(newTimer);
@@ -984,7 +1009,7 @@ void CPVRGUIActionsTimers::AnnounceReminder(const std::shared_ptr<CPVRTimerInfoT
}
else
{
- int iDuration = (timer->EndAsUTC() - timer->StartAsUTC()).GetSecondsTotal() / 60;
+ const int iDuration{(timer->EndAsUTC() - timer->StartAsUTC()).GetSecondsTotal()};
newTimer = CPVRTimerInfoTag::CreateTimerTag(timer->Channel(), timer->StartAsUTC(), iDuration);
}
diff --git a/xbmc/pvr/timers/PVRTimerInfoTag.cpp b/xbmc/pvr/timers/PVRTimerInfoTag.cpp
index 6f5ea746ea..9c49d9d850 100644
--- a/xbmc/pvr/timers/PVRTimerInfoTag.cpp
+++ b/xbmc/pvr/timers/PVRTimerInfoTag.cpp
@@ -791,7 +791,7 @@ std::shared_ptr<CPVRTimerInfoTag> CPVRTimerInfoTag::CreateFromDate(
if (bInstantStart)
epgTag = channel->GetEPGNow();
else if (channel->GetEPG())
- epgTag = channel->GetEPG()->GetTagBetween(start, start + CDateTimeSpan(0, 0, iDuration, 0));
+ epgTag = channel->GetEPG()->GetTagBetween(start, start + CDateTimeSpan(0, 0, 0, iDuration));
}
std::shared_ptr<CPVRTimerInfoTag> newTimer;
@@ -853,16 +853,17 @@ std::shared_ptr<CPVRTimerInfoTag> CPVRTimerInfoTag::CreateFromDate(
if (iDuration == DEFAULT_PVRRECORD_INSTANTRECORDTIME)
iDuration = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
- CSettings::SETTING_PVRRECORD_INSTANTRECORDTIME);
+ CSettings::SETTING_PVRRECORD_INSTANTRECORDTIME) *
+ 60;
if (bInstantStart)
{
- CDateTime endTime = now + CDateTimeSpan(0, 0, iDuration ? iDuration : 120, 0);
+ const CDateTime endTime{now + CDateTimeSpan(0, 0, 0, iDuration ? iDuration : 2 * 60 * 60)};
newTimer->SetEndFromUTC(endTime);
}
else
{
- CDateTime endTime = start + CDateTimeSpan(0, 0, iDuration ? iDuration : 120, 0);
+ const CDateTime endTime{start + CDateTimeSpan(0, 0, 0, iDuration ? iDuration : 2 * 60 * 60)};
newTimer->SetEndFromUTC(endTime);
}
diff --git a/xbmc/pvr/timers/PVRTimers.cpp b/xbmc/pvr/timers/PVRTimers.cpp
index ccf719091a..a6d0ae395d 100644
--- a/xbmc/pvr/timers/PVRTimers.cpp
+++ b/xbmc/pvr/timers/PVRTimers.cpp
@@ -635,8 +635,8 @@ bool CPVRTimers::UpdateEntries(int iMaxNotificationDelay)
{
const CDateTimeSpan duration = timer->EndAsUTC() - timer->StartAsUTC();
const std::shared_ptr<CPVRTimerInfoTag> childTimer =
- CPVRTimerInfoTag::CreateReminderFromDate(
- nextStart, duration.GetSecondsTotal() / 60, timer);
+ CPVRTimerInfoTag::CreateReminderFromDate(nextStart, duration.GetSecondsTotal(),
+ timer);
if (childTimer)
{
bChanged = true;
@@ -1062,7 +1062,7 @@ bool CPVRTimers::AddLocalTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag, boo
{
const CDateTimeSpan duration = persistedTimer->EndAsUTC() - persistedTimer->StartAsUTC();
const std::shared_ptr<CPVRTimerInfoTag> childTimer =
- CPVRTimerInfoTag::CreateReminderFromDate(nextStart, duration.GetSecondsTotal() / 60,
+ CPVRTimerInfoTag::CreateReminderFromDate(nextStart, duration.GetSecondsTotal(),
persistedTimer);
if (childTimer)
{
diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
index 0f4c5a7871..051636cb05 100644
--- a/xbmc/settings/AdvancedSettings.h
+++ b/xbmc/settings/AdvancedSettings.h
@@ -13,6 +13,7 @@
#include "settings/lib/ISettingsHandler.h"
#include "utils/SortUtils.h"
+#include <cstdint>
#include <set>
#include <string>
#include <utility>
diff --git a/xbmc/storage/DetectDVDType.cpp b/xbmc/storage/DetectDVDType.cpp
index 3a3a3a08a8..91fd7deecb 100644
--- a/xbmc/storage/DetectDVDType.cpp
+++ b/xbmc/storage/DetectDVDType.cpp
@@ -389,13 +389,6 @@ void CDetectDVDMedia::WaitMediaReady()
std::unique_lock<CCriticalSection> waitLock(m_muReadingMedia);
}
-// Static function
-// Returns status of the DVD Drive
-bool CDetectDVDMedia::DriveReady()
-{
- return m_DriveState == DriveState::READY;
-}
-
DriveState CDetectDVDMedia::GetDriveState()
{
return m_DriveState;
diff --git a/xbmc/storage/DetectDVDType.h b/xbmc/storage/DetectDVDType.h
index 500a10f574..a97944509f 100644
--- a/xbmc/storage/DetectDVDType.h
+++ b/xbmc/storage/DetectDVDType.h
@@ -42,7 +42,6 @@ public:
static void WaitMediaReady();
static bool IsDiscInDrive();
- static bool DriveReady();
static DriveState GetDriveState();
static CCdInfo* GetCdInfo();
static CEvent m_evAutorun;
diff --git a/xbmc/utils/Archive.h b/xbmc/utils/Archive.h
index a1af0c3cf8..341c07d779 100644
--- a/xbmc/utils/Archive.h
+++ b/xbmc/utils/Archive.h
@@ -8,6 +8,7 @@
#pragma once
+#include <cstdint>
#include <cstring>
#include <memory>
#include <string>
diff --git a/xbmc/utils/CharArrayParser.cpp b/xbmc/utils/CharArrayParser.cpp
index 5aeec2040b..ec5af70a9c 100644
--- a/xbmc/utils/CharArrayParser.cpp
+++ b/xbmc/utils/CharArrayParser.cpp
@@ -156,11 +156,19 @@ bool CCharArrayParser::ReadNextLine(std::string& line)
line.assign(m_data + m_position, lineLimit - m_position);
m_position = lineLimit;
+ // Skip EOL chars
if (m_data[m_position] == '\r')
{
m_position++;
+
+ if (m_data[m_position] == '\n')
+ m_position++;
+ // Malformed EOL as \r\r\n
+ else if (m_position + 1 <= m_limit && m_data[m_position] == '\r' &&
+ m_data[m_position + 1] == '\n')
+ m_position += 2;
}
- if (m_data[m_position] == '\n')
+ else if (m_data[m_position] == '\n')
{
m_position++;
}
diff --git a/xbmc/utils/EGLFence.cpp b/xbmc/utils/EGLFence.cpp
index 9d0065bdaf..58a9ec1683 100644
--- a/xbmc/utils/EGLFence.cpp
+++ b/xbmc/utils/EGLFence.cpp
@@ -133,11 +133,7 @@ void CEGLFence::WaitSyncCPU()
if (!m_kmsFence)
return;
- EGLint status{EGL_FALSE};
-
- while (status != EGL_CONDITION_SATISFIED_KHR)
- status = m_eglClientWaitSyncKHR(m_display, m_kmsFence, 0, EGL_FOREVER_KHR);
-
- m_eglDestroySyncKHR(m_display, m_kmsFence);
+ if (m_eglClientWaitSyncKHR(m_display, m_kmsFence, 0, EGL_FOREVER_KHR) != EGL_FALSE)
+ m_eglDestroySyncKHR(m_display, m_kmsFence);
}
#endif
diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp
index f333bb334b..20b8724977 100644
--- a/xbmc/video/VideoDatabase.cpp
+++ b/xbmc/video/VideoDatabase.cpp
@@ -4994,6 +4994,8 @@ void CVideoDatabase::SetArtForItem(int mediaId, const MediaType &mediaType, cons
sql = PrepareSQL("INSERT INTO art(media_id, media_type, type, url) VALUES (%d, '%s', '%s', '%s')", mediaId, mediaType.c_str(), artType.c_str(), url.c_str());
m_pDS->exec(sql);
}
+
+ AnnounceUpdate(mediaType, mediaId);
}
catch (...)
{
diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp
index c02ee60282..10cc30a6c9 100644
--- a/xbmc/video/VideoInfoScanner.cpp
+++ b/xbmc/video/VideoInfoScanner.cpp
@@ -49,6 +49,7 @@
#include "video/VideoFileItemClassify.h"
#include "video/VideoManagerTypes.h"
#include "video/VideoThumbLoader.h"
+#include "video/VideoUtils.h"
#include "video/dialogs/GUIDialogVideoManagerExtras.h"
#include "video/dialogs/GUIDialogVideoManagerVersions.h"
@@ -59,7 +60,7 @@
using namespace XFILE;
using namespace ADDON;
using namespace KODI::MESSAGING;
-using namespace KODI::VIDEO;
+using namespace KODI;
using KODI::MESSAGING::HELPERS::DialogResponse;
using KODI::UTILITY::CDigest;
@@ -1527,7 +1528,7 @@ namespace KODI::VIDEO
if (content == CONTENT_MOVIES)
{
// find local trailer first
- std::string strTrailer = pItem->FindTrailer();
+ std::string strTrailer = UTILS::FindTrailer(*pItem);
if (!strTrailer.empty())
movieDetails.m_strTrailer = strTrailer;
diff --git a/xbmc/video/VideoUtils.cpp b/xbmc/video/VideoUtils.cpp
index eb6ab9674d..73f38e4ead 100644
--- a/xbmc/video/VideoUtils.cpp
+++ b/xbmc/video/VideoUtils.cpp
@@ -13,12 +13,18 @@
#include "ServiceBroker.h"
#include "Util.h"
#include "filesystem/Directory.h"
+#include "filesystem/StackDirectory.h"
#include "filesystem/VideoDatabaseDirectory/QueryParams.h"
+#include "network/NetworkFileItemClassify.h"
#include "playlists/PlayListFileItemClassify.h"
+#include "pvr/filesystem/PVRGUIDirectory.h"
+#include "settings/AdvancedSettings.h"
#include "settings/SettingUtils.h"
#include "settings/Settings.h"
#include "settings/SettingsComponent.h"
#include "settings/lib/Setting.h"
+#include "utils/ArtUtils.h"
+#include "utils/FileExtensionProvider.h"
#include "utils/FileUtils.h"
#include "utils/URIUtils.h"
#include "utils/log.h"
@@ -41,15 +47,17 @@ KODI::VIDEO::UTILS::ResumeInformation GetFolderItemResumeInformation(const CFile
return {};
CFileItem folderItem(item);
- if ((!folderItem.HasProperty("inprogressepisodes") || // season/show
- (folderItem.GetProperty("inprogressepisodes").asInteger() == 0)) &&
- (!folderItem.HasProperty("inprogress") || // movie set
- (folderItem.GetProperty("inprogress").asInteger() == 0)))
+ if (!folderItem.HasProperty("inprogressepisodes") && // season/show/recordings
+ !folderItem.HasProperty("inprogress")) // movie set
{
- CVideoDatabase db;
- if (db.Open())
+ if (URIUtils::IsPVRRecordingFileOrFolder(folderItem.GetPath()))
+ {
+ PVR::CPVRGUIDirectory::GetRecordingsDirectoryInfo(folderItem);
+ }
+ else
{
- if (!folderItem.HasProperty("inprogressepisodes") && !folderItem.HasProperty("inprogress"))
+ CVideoDatabase db;
+ if (db.Open())
{
XFILE::VIDEODATABASEDIRECTORY::CQueryParams params;
XFILE::VIDEODATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(item.GetPath(), params);
@@ -79,7 +87,6 @@ KODI::VIDEO::UTILS::ResumeInformation GetFolderItemResumeInformation(const CFile
db.GetSetInfo(static_cast<int>(params.GetSetId()), details, &folderItem);
}
}
- db.Close();
}
}
@@ -185,6 +192,86 @@ KODI::VIDEO::UTILS::ResumeInformation GetNonFolderItemResumeInformation(const CF
namespace KODI::VIDEO::UTILS
{
+
+std::string FindTrailer(const CFileItem& item)
+{
+ std::string strFile2;
+ std::string strFile = item.GetPath();
+ if (item.IsStack())
+ {
+ std::string strPath;
+ URIUtils::GetParentPath(item.GetPath(), strPath);
+ XFILE::CStackDirectory dir;
+ std::string strPath2;
+ strPath2 = dir.GetStackedTitlePath(strFile);
+ strFile = URIUtils::AddFileToFolder(strPath, URIUtils::GetFileName(strPath2));
+ CFileItem sitem(dir.GetFirstStackedFile(item.GetPath()), false);
+ std::string strTBNFile(URIUtils::ReplaceExtension(ART::GetTBNFile(sitem), "-trailer"));
+ strFile2 = URIUtils::AddFileToFolder(strPath, URIUtils::GetFileName(strTBNFile));
+ }
+ if (URIUtils::IsInRAR(strFile) || URIUtils::IsInZIP(strFile))
+ {
+ std::string strPath = URIUtils::GetDirectory(strFile);
+ std::string strParent;
+ URIUtils::GetParentPath(strPath, strParent);
+ strFile = URIUtils::AddFileToFolder(strParent, URIUtils::GetFileName(item.GetPath()));
+ }
+
+ // no local trailer available for these
+ if (NETWORK::IsInternetStream(item) || URIUtils::IsUPnP(strFile) || URIUtils::IsBluray(strFile) ||
+ item.IsLiveTV() || item.IsPlugin() || item.IsDVD())
+ return "";
+
+ std::string strDir = URIUtils::GetDirectory(strFile);
+ CFileItemList items;
+ XFILE::CDirectory::GetDirectory(
+ strDir, items, CServiceBroker::GetFileExtensionProvider().GetVideoExtensions(),
+ XFILE::DIR_FLAG_READ_CACHE | XFILE::DIR_FLAG_NO_FILE_INFO | XFILE::DIR_FLAG_NO_FILE_DIRS);
+ URIUtils::RemoveExtension(strFile);
+ strFile += "-trailer";
+ std::string strFile3 = URIUtils::AddFileToFolder(strDir, "movie-trailer");
+
+ // Precompile our REs
+ VECCREGEXP matchRegExps;
+ CRegExp tmpRegExp(true, CRegExp::autoUtf8);
+ const std::vector<std::string>& strMatchRegExps =
+ CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_trailerMatchRegExps;
+
+ for (const auto& strRegExp : strMatchRegExps)
+ {
+ if (tmpRegExp.RegComp(strRegExp))
+ matchRegExps.push_back(tmpRegExp);
+ }
+
+ std::string strTrailer;
+ for (int i = 0; i < items.Size(); i++)
+ {
+ std::string strCandidate = items[i]->GetPath();
+ URIUtils::RemoveExtension(strCandidate);
+ if (StringUtils::EqualsNoCase(strCandidate, strFile) ||
+ StringUtils::EqualsNoCase(strCandidate, strFile2) ||
+ StringUtils::EqualsNoCase(strCandidate, strFile3))
+ {
+ strTrailer = items[i]->GetPath();
+ break;
+ }
+ else
+ {
+ for (auto& expr : matchRegExps)
+ {
+ if (expr.RegFind(strCandidate) != -1)
+ {
+ strTrailer = items[i]->GetPath();
+ i = items.Size();
+ break;
+ }
+ }
+ }
+ }
+
+ return strTrailer;
+}
+
std::string GetOpticalMediaPath(const CFileItem& item)
{
auto exists = [&item](const std::string& file)
diff --git a/xbmc/video/VideoUtils.h b/xbmc/video/VideoUtils.h
index c344072ffe..2ee611c4e8 100644
--- a/xbmc/video/VideoUtils.h
+++ b/xbmc/video/VideoUtils.h
@@ -14,6 +14,13 @@ class CFileItem;
namespace KODI::VIDEO::UTILS
{
+
+/*! \brief
+ * Find a local trailer file for a given file item
+ * \return non-empty string with path of trailer if found
+ */
+std::string FindTrailer(const CFileItem& item);
+
/*!
\brief Check whether an item is an optical media folder or its parent.
This will return the non-empty path to the playable entry point of the media
diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
index 7d93996ba5..d297a15634 100644
--- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
+++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
@@ -59,6 +59,7 @@
#include "video/VideoItemArtworkHandler.h"
#include "video/VideoLibraryQueue.h"
#include "video/VideoThumbLoader.h"
+#include "video/VideoUtils.h"
#include "video/dialogs/GUIDialogVideoManagerExtras.h"
#include "video/dialogs/GUIDialogVideoManagerVersions.h"
#include "video/guilib/VideoGUIUtils.h"
@@ -453,7 +454,7 @@ void CGUIDialogVideoInfo::SetMovie(const CFileItem *item)
if (m_movieItem->GetVideoInfoTag()->m_strTrailer.empty() ||
URIUtils::IsInternetStream(m_movieItem->GetVideoInfoTag()->m_strTrailer))
{
- std::string localTrailer = m_movieItem->FindTrailer();
+ std::string localTrailer = VIDEO::UTILS::FindTrailer(*m_movieItem);
if (!localTrailer.empty())
{
m_movieItem->GetVideoInfoTag()->m_strTrailer = localTrailer;
@@ -863,8 +864,9 @@ void AddHardCodedAndExtendedArtTypes(std::vector<std::string>& artTypes, const C
}
// Add art types currently assigned to the media item
-void AddCurrentArtTypes(std::vector<std::string>& artTypes, const CVideoInfoTag& tag,
- CVideoDatabase& db)
+void AddCurrentArtTypes(std::vector<std::string>& artTypes,
+ const CVideoInfoTag& tag,
+ CVideoDatabase& db)
{
std::map<std::string, std::string> currentArt;
@@ -882,8 +884,9 @@ void AddCurrentArtTypes(std::vector<std::string>& artTypes, const CVideoInfoTag&
}
// Add art types that exist for other media items of the same type
-void AddMediaTypeArtTypes(std::vector<std::string>& artTypes, const CVideoInfoTag& tag,
- CVideoDatabase& db)
+void AddMediaTypeArtTypes(std::vector<std::string>& artTypes,
+ const CVideoInfoTag& tag,
+ CVideoDatabase& db)
{
std::vector<std::string> dbArtTypes;
db.GetArtTypes(tag.m_type, dbArtTypes);
@@ -895,8 +898,9 @@ void AddMediaTypeArtTypes(std::vector<std::string>& artTypes, const CVideoInfoTa
}
// Add art types from available but unassigned artwork for this media item
-void AddAvailableArtTypes(std::vector<std::string>& artTypes, const CVideoInfoTag& tag,
- CVideoDatabase& db)
+void AddAvailableArtTypes(std::vector<std::string>& artTypes,
+ const CVideoInfoTag& tag,
+ CVideoDatabase& db)
{
for (const auto& artType : db.GetAvailableArtTypesForItem(tag.m_iDbId, tag.m_type))
{
@@ -929,6 +933,7 @@ public:
bool ChooseArtType();
const std::string& GetArtType() const { return m_artType; }
+ void UpdateArtType(const std::string& type, const std::string& art) const;
private:
std::shared_ptr<CFileItem> m_item;
@@ -937,6 +942,15 @@ private:
std::string m_artType;
};
+void CArtTypeChooser::UpdateArtType(const std::string& type, const std::string& art) const
+{
+ m_item->SetArt(type, art);
+ if (!m_items.IsEmpty())
+ for (auto& item : m_items)
+ if (item->GetProperty("type") == type)
+ item->SetArt("thumb", art);
+}
+
bool CArtTypeChooser::ChooseArtType()
{
CGUIDialogSelect* dialog =
@@ -1831,7 +1845,10 @@ bool CGUIDialogVideoInfo::ChooseAndManageVideoItemArtwork(const std::shared_ptr<
if (!chooser.ChooseArtType())
break;
- result = ManageVideoItemArtwork(item, item->GetVideoInfoTag()->m_type, chooser.GetArtType());
+ const std::string chosenArtType{chooser.GetArtType()};
+ result = ManageVideoItemArtwork(item, item->GetVideoInfoTag()->m_type, chosenArtType);
+ if (result)
+ chooser.UpdateArtType(chosenArtType, item->GetArt(chosenArtType));
} while (true);
diff --git a/xbmc/video/test/TestVideoUtils.cpp b/xbmc/video/test/TestVideoUtils.cpp
index 579fff0180..9feb832e5b 100644
--- a/xbmc/video/test/TestVideoUtils.cpp
+++ b/xbmc/video/test/TestVideoUtils.cpp
@@ -7,6 +7,7 @@
*/
#include "FileItem.h"
+#include "URL.h"
#include "Util.h"
#include "filesystem/Directory.h"
#include "platform/Filesystem.h"
@@ -22,12 +23,23 @@
using namespace KODI;
namespace fs = KODI::PLATFORM::FILESYSTEM;
+namespace
+{
+
using OptDef = std::pair<std::string, bool>;
class OpticalMediaPathTest : public testing::WithParamInterface<OptDef>, public testing::Test
{
};
+using TrailerDef = std::pair<std::string, std::string>;
+
+class TrailerTest : public testing::WithParamInterface<TrailerDef>, public testing::Test
+{
+};
+
+} // namespace
+
TEST_P(OpticalMediaPathTest, GetOpticalMediaPath)
{
std::error_code ec;
@@ -57,3 +69,53 @@ const auto mediapath_tests = std::array{
};
INSTANTIATE_TEST_SUITE_P(TestVideoUtils, OpticalMediaPathTest, testing::ValuesIn(mediapath_tests));
+
+TEST_P(TrailerTest, FindTrailer)
+{
+ std::string temp_path;
+ if (!GetParam().second.empty())
+ {
+ std::error_code ec;
+ temp_path = fs::create_temp_directory(ec);
+ EXPECT_FALSE(ec);
+ XFILE::CDirectory::Create(temp_path);
+ const std::string file_path = URIUtils::AddFileToFolder(temp_path, GetParam().second);
+ {
+ std::ofstream of(file_path);
+ }
+ URIUtils::AddSlashAtEnd(temp_path);
+ }
+
+ std::string input_path = GetParam().first;
+ if (!temp_path.empty())
+ {
+ StringUtils::Replace(input_path, "#DIRECTORY#", temp_path);
+ StringUtils::Replace(input_path, "#URLENCODED_DIRECTORY#", CURL::Encode(temp_path));
+ }
+
+ CFileItem item(input_path, false);
+ EXPECT_EQ(VIDEO::UTILS::FindTrailer(item),
+ GetParam().second.empty() ? ""
+ : URIUtils::AddFileToFolder(temp_path, GetParam().second));
+
+ if (!temp_path.empty())
+ XFILE::CDirectory::RemoveRecursive(temp_path);
+}
+
+const auto trailer_tests = std::array{
+ TrailerDef{"https://some.where/foo", ""},
+ TrailerDef{"upnp://1/2/3", ""},
+ TrailerDef{"bluray://1", ""},
+ TrailerDef{"pvr://foobar.pvr", ""},
+ TrailerDef{"plugin://plugin.video.foo/foo?param=1", ""},
+ TrailerDef{"dvd://1", ""},
+ TrailerDef{"stack://#DIRECTORY#foo-cd1.avi , #DIRECTORY#foo-cd2.avi", "foo-trailer.mkv"},
+ TrailerDef{"stack://#DIRECTORY#foo-cd1.avi , #DIRECTORY#foo-cd2.avi", "foo-cd1-trailer.avi"},
+ TrailerDef{"stack://#DIRECTORY#foo-cd1.avi , #DIRECTORY#foo-cd2.avi", "movie-trailer.mp4"},
+ TrailerDef{"zip://#URLENCODED_DIRECTORY#bar.zip/bar.avi", "bar-trailer.mov"},
+ TrailerDef{"zip://#URLENCODED_DIRECTORY#bar.zip/bar.mkv", "movie-trailer.ogm"},
+ TrailerDef{"#DIRECTORY#bar.mkv", "bar-trailer.mkv"},
+ TrailerDef{"#DIRECTORY#bar.mkv", "movie-trailer.avi"},
+};
+
+INSTANTIATE_TEST_SUITE_P(TestVideoUtils, TrailerTest, testing::ValuesIn(trailer_tests));
diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp
index a875ae4bfa..d231a809f7 100644
--- a/xbmc/video/windows/GUIWindowVideoBase.cpp
+++ b/xbmc/video/windows/GUIWindowVideoBase.cpp
@@ -65,7 +65,6 @@
#include "video/guilib/VideoGUIUtils.h"
#include "video/guilib/VideoPlayActionProcessor.h"
#include "video/guilib/VideoSelectActionProcessor.h"
-#include "video/guilib/VideoVersionHelper.h"
#include "view/GUIViewState.h"
#include <memory>
diff --git a/xbmc/windowing/gbm/drm/DRMAtomic.cpp b/xbmc/windowing/gbm/drm/DRMAtomic.cpp
index ff7f137d60..70ae92e948 100644
--- a/xbmc/windowing/gbm/drm/DRMAtomic.cpp
+++ b/xbmc/windowing/gbm/drm/DRMAtomic.cpp
@@ -149,6 +149,11 @@ void CDRMAtomic::DrmAtomicCommit(int fb_id, int flags, bool rendered, bool video
{
CLog::Log(LOGERROR, "CDRMAtomic::{} - atomic commit failed: {}", __FUNCTION__,
strerror(errno));
+ m_atomicRequestQueue.pop_back();
+ }
+ else if (m_atomicRequestQueue.size() > 1)
+ {
+ m_atomicRequestQueue.pop_front();
}
if (m_inFenceFd != -1)
@@ -164,9 +169,6 @@ void CDRMAtomic::DrmAtomicCommit(int fb_id, int flags, bool rendered, bool video
strerror(errno));
}
- if (m_atomicRequestQueue.size() > 1)
- m_atomicRequestQueue.pop_back();
-
m_atomicRequestQueue.emplace_back(std::make_unique<CDRMAtomicRequest>());
m_req = m_atomicRequestQueue.back().get();
}
diff --git a/xbmc/windowing/gbm/drm/DRMObject.cpp b/xbmc/windowing/gbm/drm/DRMObject.cpp
index 5ffce40fa3..99dda24490 100644
--- a/xbmc/windowing/gbm/drm/DRMObject.cpp
+++ b/xbmc/windowing/gbm/drm/DRMObject.cpp
@@ -105,6 +105,25 @@ std::optional<uint64_t> CDRMObject::GetPropertyValue(std::string_view name,
return {};
}
+std::optional<std::span<uint64_t, 2>> CDRMObject::GetRangePropertyLimits(std::string_view name)
+{
+ auto property = std::find_if(m_propsInfo.begin(), m_propsInfo.end(),
+ [&name](const auto& prop) { return prop->name == name; });
+
+ if (property == m_propsInfo.end())
+ return {};
+
+ auto prop = property->get();
+
+ if (!static_cast<bool>(drm_property_type_is(prop, DRM_MODE_PROP_RANGE)))
+ return {};
+
+ if (prop->count_values != 2)
+ return {};
+
+ return std::make_optional<std::span<uint64_t, 2>>(prop->values, 2);
+}
+
bool CDRMObject::SetProperty(const std::string& name, uint64_t value)
{
auto property = std::find_if(m_propsInfo.begin(), m_propsInfo.end(),
@@ -130,3 +149,14 @@ bool CDRMObject::SupportsProperty(const std::string& name)
return false;
}
+
+std::optional<bool> CDRMObject::IsPropertyImmutable(std::string_view name)
+{
+ auto property = std::find_if(m_propsInfo.begin(), m_propsInfo.end(),
+ [&name](const auto& prop) { return prop->name == name; });
+
+ if (property == m_propsInfo.end())
+ return {};
+
+ return static_cast<bool>(drm_property_type_is(property->get(), DRM_MODE_PROP_IMMUTABLE));
+}
diff --git a/xbmc/windowing/gbm/drm/DRMObject.h b/xbmc/windowing/gbm/drm/DRMObject.h
index c4200b1a86..39ba28a004 100644
--- a/xbmc/windowing/gbm/drm/DRMObject.h
+++ b/xbmc/windowing/gbm/drm/DRMObject.h
@@ -12,6 +12,7 @@
#include <cstdint>
#include <memory>
#include <optional>
+#include <span>
#include <string_view>
#include <vector>
@@ -40,6 +41,8 @@ public:
bool SetProperty(const std::string& name, uint64_t value);
bool SupportsProperty(const std::string& name);
+ std::optional<bool> IsPropertyImmutable(std::string_view name);
+ std::optional<std::span<uint64_t, 2>> GetRangePropertyLimits(std::string_view name);
protected:
explicit CDRMObject(int fd);
diff --git a/xbmc/windowing/gbm/drm/DRMUtils.cpp b/xbmc/windowing/gbm/drm/DRMUtils.cpp
index 3dd4ee9783..22db758ab6 100644
--- a/xbmc/windowing/gbm/drm/DRMUtils.cpp
+++ b/xbmc/windowing/gbm/drm/DRMUtils.cpp
@@ -181,77 +181,130 @@ bool CDRMUtils::FindPreferredMode()
return true;
}
-bool CDRMUtils::FindPlanes()
+bool CDRMUtils::FindGuiPlane()
{
- for (size_t i = 0; i < m_crtcs.size(); i++)
- {
- if (!(m_encoder->GetPossibleCrtcs() & (1 << i)))
+ /* find the gui plane which support ARGB and 8bit or 10 bit XRGB
+ * prefer the one which does not support NV12, because it can be re-used in future for video
+ * prefer the highest id number because they are listed on top where zpos is not available
+ * and use the gui plane crtc as the crtc
+ * */
+ CDRMPlane* gui_plane_nv12{nullptr};
+ CDRMPlane* gui_plane{nullptr};
+ CDRMCrtc* gui_crtc_nv12{nullptr};
+ CDRMCrtc* gui_crtc{nullptr};
+
+ for (size_t crtc_offset = 0; crtc_offset < m_crtcs.size(); crtc_offset++)
+ {
+ if (!(m_encoder->GetPossibleCrtcs() & (1 << crtc_offset)))
continue;
- auto videoPlane = std::find_if(m_planes.begin(), m_planes.end(), [&i](auto& plane) {
- if (plane->GetPossibleCrtcs() & (1 << i))
- {
- return plane->SupportsFormat(DRM_FORMAT_NV12);
- }
- return false;
- });
-
- uint32_t videoPlaneId{0};
-
- if (videoPlane != m_planes.end())
- videoPlaneId = videoPlane->get()->GetPlaneId();
-
- auto guiPlane =
- std::find_if(m_planes.begin(), m_planes.end(), [&i, &videoPlaneId](auto& plane) {
- if (plane->GetPossibleCrtcs() & (1 << i))
- {
- return (plane->GetPlaneId() != videoPlaneId &&
- (videoPlaneId == 0 || plane->SupportsFormat(DRM_FORMAT_ARGB8888)) &&
- (plane->SupportsFormat(DRM_FORMAT_XRGB2101010) ||
- plane->SupportsFormat(DRM_FORMAT_XRGB8888)));
- }
- return false;
- });
-
- if (videoPlane != m_planes.end() && guiPlane != m_planes.end())
+ for (auto& plane : m_planes)
{
- m_crtc = m_crtcs[i].get();
- m_video_plane = videoPlane->get();
- m_gui_plane = guiPlane->get();
- break;
- }
+ if (!(plane.get()->GetPossibleCrtcs() & (1 << crtc_offset)))
+ continue;
- if (guiPlane != m_planes.end())
- {
- if (!m_crtc && m_encoder->GetCrtcId() == m_crtcs[i]->GetCrtcId())
+ if (plane.get()->SupportsFormat(DRM_FORMAT_ARGB8888) &&
+ (plane.get()->SupportsFormat(DRM_FORMAT_XRGB2101010) ||
+ plane.get()->SupportsFormat(DRM_FORMAT_XRGB8888)))
{
- m_crtc = m_crtcs[i].get();
- m_gui_plane = guiPlane->get();
- m_video_plane = nullptr;
+ if (plane.get()->SupportsFormat(DRM_FORMAT_NV12) &&
+ (gui_plane_nv12 == nullptr || gui_plane_nv12->GetId() < plane.get()->GetId()))
+ {
+ gui_plane_nv12 = plane.get();
+ gui_crtc_nv12 = m_crtcs[crtc_offset].get();
+ }
+ else if (!plane.get()->SupportsFormat(DRM_FORMAT_NV12) &&
+ (gui_plane == nullptr || gui_plane->GetId() < plane.get()->GetId()))
+ {
+ gui_plane = plane.get();
+ gui_crtc = m_crtcs[crtc_offset].get();
+ }
}
}
}
- CLog::Log(LOGINFO, "CDRMUtils::{} - using crtc: {}", __FUNCTION__, m_crtc->GetCrtcId());
-
- // video plane may not be available
- if (m_video_plane)
- CLog::Log(LOGDEBUG, "CDRMUtils::{} - using video plane {}", __FUNCTION__,
- m_video_plane->GetPlaneId());
-
- if (m_gui_plane->SupportsFormat(DRM_FORMAT_XRGB2101010))
+ // fallback to NV12 supporting plane
+ if (gui_plane == nullptr)
{
- m_gui_plane->SetFormat(DRM_FORMAT_XRGB2101010);
- CLog::Log(LOGDEBUG, "CDRMUtils::{} - using 10bit gui plane {}", __FUNCTION__,
- m_gui_plane->GetPlaneId());
+ gui_crtc = gui_crtc_nv12;
+ gui_plane = gui_plane_nv12;
}
- else
+
+ if (gui_plane != nullptr)
{
- m_gui_plane->SetFormat(DRM_FORMAT_XRGB8888);
- CLog::Log(LOGDEBUG, "CDRMUtils::{} - using gui plane {}", __FUNCTION__,
- m_gui_plane->GetPlaneId());
+ m_crtc = gui_crtc;
+ m_gui_plane = gui_plane;
+
+ CLog::Log(LOGINFO, "CDRMUtils::{} - using crtc: {}", __FUNCTION__, m_crtc->GetCrtcId());
+ if (m_gui_plane->SupportsFormat(DRM_FORMAT_XRGB2101010))
+ {
+ m_gui_plane->SetFormat(DRM_FORMAT_XRGB2101010);
+ CLog::Log(LOGDEBUG, "CDRMUtils::{} - using 10bit gui plane {}", __FUNCTION__,
+ m_gui_plane->GetPlaneId());
+ }
+ else
+ {
+ m_gui_plane->SetFormat(DRM_FORMAT_XRGB8888);
+ CLog::Log(LOGDEBUG, "CDRMUtils::{} - using gui plane {}", __FUNCTION__,
+ m_gui_plane->GetPlaneId());
+ }
+ return true;
}
+ CLog::Log(LOGERROR, "CDRMUtils::{} - Can not find a GUI plane", __FUNCTION__);
+ return false;
+}
+
+bool CDRMUtils::FindVideoPlane(uint32_t format, uint64_t modifier)
+{
+ bool supports_zpos = m_gui_plane->SupportsProperty("zpos");
+ bool zpos_immutable = supports_zpos && m_gui_plane->IsPropertyImmutable("zpos").value();
+
+ auto crtc_offset = std::distance(
+ m_crtcs.begin(),
+ std::find_if(m_crtcs.begin(), m_crtcs.end(),
+ [this](auto& crtc) { return crtc->GetCrtcId() == m_crtc->GetCrtcId(); }));
+
+ auto guiplane_id = m_gui_plane->GetId();
+ auto videoPlane = std::find_if(m_planes.begin(), m_planes.end(),
+ [&crtc_offset, &format, &modifier, &guiplane_id](auto& plane)
+ {
+ if (plane->GetPossibleCrtcs() & (1 << crtc_offset))
+ {
+ return (guiplane_id != plane->GetPlaneId() &&
+ plane->SupportsFormatAndModifier(format, modifier));
+ }
+ return false;
+ });
+
+ if (videoPlane == m_planes.end())
+ {
+ CLog::Log(LOGERROR,
+ "CDRMUtils::{} - Can not find a Video Plane plane for format {}, modifier {}",
+ __FUNCTION__, format, modifier);
+ return false;
+ }
+
+ m_video_plane = videoPlane->get();
+ CLog::Log(LOGDEBUG, "CDRMUtils::{} - using video plane {}", __FUNCTION__,
+ m_video_plane->GetPlaneId());
+
+ if (!supports_zpos || zpos_immutable)
+ return true;
+
+ // re-sort the video and gui planes
+ auto limits = m_gui_plane->GetRangePropertyLimits("zpos");
+
+ if (!limits)
+ return true;
+
+ m_gui_plane->SetProperty("zpos", limits.value()[1]);
+ m_video_plane->SetProperty("zpos", limits.value()[0]);
+ CLog::Log(LOGDEBUG, "CDRMUtils::{} - gui plane id,zpos: {}, {}", __FUNCTION__,
+ m_gui_plane->GetId(), limits.value()[1]);
+ CLog::Log(LOGDEBUG, "CDRMUtils::{} - video plane id,zpos: {}, {}", __FUNCTION__,
+ m_video_plane->GetId(), limits.value()[0]);
+
return true;
}
@@ -467,9 +520,11 @@ bool CDRMUtils::InitDrm()
if (!FindCrtc())
return false;
- if (!FindPlanes())
+ if (!FindGuiPlane())
return false;
+ FindVideoPlane(DRM_FORMAT_NV12, DRM_FORMAT_MOD_LINEAR);
+
if (!FindPreferredMode())
return false;
diff --git a/xbmc/windowing/gbm/drm/DRMUtils.h b/xbmc/windowing/gbm/drm/DRMUtils.h
index f92f716fc4..b99a6dc4fe 100644
--- a/xbmc/windowing/gbm/drm/DRMUtils.h
+++ b/xbmc/windowing/gbm/drm/DRMUtils.h
@@ -64,6 +64,8 @@ public:
static uint32_t FourCCWithoutAlpha(uint32_t fourcc);
void SetInFenceFd(int fd) { m_inFenceFd = fd; }
+ bool FindVideoPlane(uint32_t format, uint64_t modifier);
+ bool FindGuiPlane();
int TakeOutFenceFd()
{
int fd{-1};
@@ -89,13 +91,13 @@ protected:
int m_inFenceFd{-1};
int m_outFenceFd{-1};
+ std::vector<std::unique_ptr<CDRMCrtc>> m_crtcs;
std::vector<std::unique_ptr<CDRMPlane>> m_planes;
private:
bool FindConnector();
bool FindEncoder();
bool FindCrtc();
- bool FindPlanes();
bool FindPreferredMode();
bool RestoreOriginalMode();
RESOLUTION_INFO GetResolutionInfo(drmModeModeInfoPtr mode);
@@ -106,7 +108,6 @@ private:
std::vector<std::unique_ptr<CDRMConnector>> m_connectors;
std::vector<std::unique_ptr<CDRMEncoder>> m_encoders;
- std::vector<std::unique_ptr<CDRMCrtc>> m_crtcs;
};
}