diff options
316 files changed, 2949 insertions, 1844 deletions
diff --git a/cmake/scripts/android/Install.cmake b/cmake/scripts/android/Install.cmake index f88957cc9f..b912141007 100644 --- a/cmake/scripts/android/Install.cmake +++ b/cmake/scripts/android/Install.cmake @@ -48,6 +48,7 @@ set(package_files strings.xml src/XBMCProperties.java src/XBMCVideoView.java src/XBMCFile.java + src/XBMCTextureCache.java src/XBMCURIUtils.java src/channels/SyncChannelJobService.java src/channels/SyncProgramsJobService.java diff --git a/system/shaders/GL/1.2/gl_shader_vert_clip.glsl b/system/shaders/GL/1.2/gl_shader_vert_clip.glsl new file mode 100644 index 0000000000..37d67946f5 --- /dev/null +++ b/system/shaders/GL/1.2/gl_shader_vert_clip.glsl @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#version 120 + +attribute vec4 m_attrpos; +attribute vec4 m_attrcol; +attribute vec4 m_attrcord0; +attribute vec4 m_attrcord1; +varying vec4 m_cord0; +varying vec4 m_cord1; +varying vec4 m_colour; +uniform mat4 m_matrix; +uniform vec4 m_shaderClip; +uniform vec4 m_cordStep; + +// this shader can be used in cases where clipping via glScissor() is not +// possible (e.g. when rotating). it can't discard triangles, but it may +// degenerate them. + +void main () +{ + // limit the vertices to the clipping area + vec4 position = m_attrpos; + position.xy = clamp(position.xy, m_shaderClip.xy, m_shaderClip.zw); + gl_Position = m_matrix * position; + + // correct texture coordinates for clipped vertices + vec2 clipDist = m_attrpos.xy - position.xy; + m_cord0.xy = m_attrcord0.xy - clipDist * m_cordStep.xy; + m_cord1.xy = m_attrcord1.xy - clipDist * m_cordStep.zw; + + m_colour = m_attrcol; +} diff --git a/system/shaders/GL/1.2/gl_shader_vert_simple.glsl b/system/shaders/GL/1.2/gl_shader_vert_simple.glsl new file mode 100644 index 0000000000..f06893a085 --- /dev/null +++ b/system/shaders/GL/1.2/gl_shader_vert_simple.glsl @@ -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. + */ + +#version 120 + +attribute vec4 m_attrpos; +attribute vec4 m_attrcol; +attribute vec4 m_attrcord0; +attribute vec4 m_attrcord1; +varying vec4 m_cord0; +varying vec4 m_cord1; +varying vec4 m_colour; +uniform mat4 m_matrix; + +void main () +{ + gl_Position = m_matrix * m_attrpos; + m_colour = m_attrcol; + m_cord0 = m_attrcord0; + m_cord1 = m_attrcord1; +} diff --git a/system/shaders/GL/1.5/gl_shader_vert_clip.glsl b/system/shaders/GL/1.5/gl_shader_vert_clip.glsl new file mode 100644 index 0000000000..2fa1c63da1 --- /dev/null +++ b/system/shaders/GL/1.5/gl_shader_vert_clip.glsl @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#version 150 + +in vec4 m_attrpos; +in vec4 m_attrcol; +in vec4 m_attrcord0; +in vec4 m_attrcord1; +out vec4 m_cord0; +out vec4 m_cord1; +out vec4 m_colour; +uniform mat4 m_matrix; +uniform vec4 m_shaderClip; +uniform vec4 m_cordStep; + +// this shader can be used in cases where clipping via glScissor() is not +// possible (e.g. when rotating). it can't discard triangles, but it may +// degenerate them. + +void main () +{ + // limit the vertices to the clipping area + vec4 position = m_attrpos; + position.xy = clamp(position.xy, m_shaderClip.xy, m_shaderClip.zw); + gl_Position = m_matrix * position; + + // correct texture coordinates for clipped vertices + vec2 clipDist = m_attrpos.xy - position.xy; + m_cord0.xy = m_attrcord0.xy - clipDist * m_cordStep.xy; + m_cord1.xy = m_attrcord1.xy - clipDist * m_cordStep.zw; + + m_colour = m_attrcol; +} diff --git a/system/shaders/GL/1.5/gl_shader_vert_simple.glsl b/system/shaders/GL/1.5/gl_shader_vert_simple.glsl new file mode 100644 index 0000000000..9c1552d7a4 --- /dev/null +++ b/system/shaders/GL/1.5/gl_shader_vert_simple.glsl @@ -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. + */ + +#version 150 + +in vec4 m_attrpos; +in vec4 m_attrcol; +in vec4 m_attrcord0; +in vec4 m_attrcord1; +out vec4 m_cord0; +out vec4 m_cord1; +out vec4 m_colour; +uniform mat4 m_matrix; + +void main () +{ + gl_Position = m_matrix * m_attrpos; + m_colour = m_attrcol; + m_cord0 = m_attrcord0; + m_cord1 = m_attrcord1; +} diff --git a/system/shaders/GLES/2.0/gles_shader_clip.vert b/system/shaders/GLES/2.0/gles_shader_clip.vert new file mode 100644 index 0000000000..513a24456c --- /dev/null +++ b/system/shaders/GLES/2.0/gles_shader_clip.vert @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#version 100 + +attribute vec4 m_attrpos; +attribute vec4 m_attrcol; +attribute vec4 m_attrcord0; +attribute vec4 m_attrcord1; +varying vec4 m_cord0; +varying vec4 m_cord1; +varying vec4 m_colour; +uniform mat4 m_matrix; +uniform vec4 m_shaderClip; +uniform vec4 m_cordStep; + +// this shader can be used in cases where clipping via glScissor() is not +// possible (e.g. when rotating). it can't discard triangles, but it may +// degenerate them. + +void main() +{ + // limit the vertices to the clipping area + vec4 position = m_attrpos; + position.xy = clamp(position.xy, m_shaderClip.xy, m_shaderClip.zw); + gl_Position = m_matrix * position; + + // correct texture coordinates for clipped vertices + vec2 clipDist = m_attrpos.xy - position.xy; + m_cord0.xy = m_attrcord0.xy - clipDist * m_cordStep.xy; + m_cord1.xy = m_attrcord1.xy - clipDist * m_cordStep.zw; + + m_colour = m_attrcol; +} diff --git a/system/shaders/GLES/2.0/gles_shader_simple.vert b/system/shaders/GLES/2.0/gles_shader_simple.vert new file mode 100644 index 0000000000..6d49788b65 --- /dev/null +++ b/system/shaders/GLES/2.0/gles_shader_simple.vert @@ -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. + */ + +#version 100 + +attribute vec4 m_attrpos; +attribute vec4 m_attrcol; +attribute vec4 m_attrcord0; +attribute vec4 m_attrcord1; +varying vec4 m_cord0; +varying vec4 m_cord1; +varying vec4 m_colour; +uniform mat4 m_matrix; + +void main() +{ + gl_Position = m_matrix * m_attrpos; + m_colour = m_attrcol; + m_cord0 = m_attrcord0; + m_cord1 = m_attrcord1; +} diff --git a/tools/Linux/kodi.sh.in b/tools/Linux/kodi.sh.in index 52d4646db5..3d86c86834 100644 --- a/tools/Linux/kodi.sh.in +++ b/tools/Linux/kodi.sh.in @@ -171,6 +171,7 @@ if command_exists gdb; then fi fi +ENV_ARGS= if [ -n "${KODI_AE_SINK}" ]; then echo "KODI_AE_SINK env variable is deprecated and will be removed in the future." @@ -197,11 +198,11 @@ if [ -n "${KODI_GL_INTERFACE}" ]; then echo "Use the --gl-interface command line switch instead." if [ "${KODI_GL_INTERFACE}" = "GLX" ]; then - ENV_ARGS="--gl-interface=glx" + ENV_ARGS="${ENV_ARGS} --gl-interface=glx" elif [ "${KODI_GL_INTERFACE}" = "EGL" ]; then - ENV_ARGS="--gl-interface=egl" + ENV_ARGS="${ENV_ARGS} --gl-interface=egl" elif [ "${KODI_GL_INTERFACE}" = "EGL_PB" ]; then - ENV_ARGS="--gl-interface=egl-pb" + ENV_ARGS="${ENV_ARGS} --gl-interface=egl-pb" fi fi diff --git a/tools/android/packaging/xbmc/src/XBMCJsonRPC.java.in b/tools/android/packaging/xbmc/src/XBMCJsonRPC.java.in index 24d9239d89..9ec4a64641 100644 --- a/tools/android/packaging/xbmc/src/XBMCJsonRPC.java.in +++ b/tools/android/packaging/xbmc/src/XBMCJsonRPC.java.in @@ -24,15 +24,15 @@ import android.net.Uri; import android.provider.BaseColumns; import android.util.Log; +import @APP_PACKAGE@.content.XBMCFileContentProvider; import @APP_PACKAGE@.model.Album; +import @APP_PACKAGE@.model.File; +import @APP_PACKAGE@.model.Media; import @APP_PACKAGE@.model.Movie; import @APP_PACKAGE@.model.MusicVideo; import @APP_PACKAGE@.model.Song; import @APP_PACKAGE@.model.TVEpisode; import @APP_PACKAGE@.model.TVShow; -import @APP_PACKAGE@.content.XBMCFileContentProvider; -import @APP_PACKAGE@.model.File; -import @APP_PACKAGE@.model.Media; public class XBMCJsonRPC { @@ -63,6 +63,7 @@ public class XBMCJsonRPC private String m_xbmc_web_url = "http://localhost:8080"; private HashSet<Integer> mRecomendationIds = new HashSet<Integer>(); + private XBMCTextureCache mTextureCache = null; private int MAX_RECOMMENDATIONS = 3; @@ -126,6 +127,7 @@ public class XBMCJsonRPC { String jsonPort = XBMCProperties.getStringProperty("xbmc.jsonPort", "8080"); m_xbmc_web_url = "http://localhost:" + jsonPort; + mTextureCache = new XBMCTextureCache(); } public String request_string(String jsonRequest) @@ -864,7 +866,7 @@ public class XBMCJsonRPC String poster = extractKeyFromArtMap(details, "poster"); if (poster != null && !poster.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); + med.setCardImageUrl(getImageUrl(poster)); med.setCardImageAspectRatio("2:3"); } // fallback to thumb @@ -873,7 +875,7 @@ public class XBMCJsonRPC poster = extractKeyFromArtMap(details, "thumb"); if (poster != null && !poster.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); + med.setCardImageUrl(getImageUrl(poster)); med.setCardImageAspectRatio("16:9"); } } @@ -881,7 +883,7 @@ public class XBMCJsonRPC String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } med.setXbmcUrl("videodb://movies/titles/" + details.get("movieid").getAsString() + "?showinfo=true"); @@ -935,7 +937,7 @@ public class XBMCJsonRPC String poster = extractKeyFromArtMap(details, "poster"); if (poster != null && !poster.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); + med.setCardImageUrl(getImageUrl(poster)); med.setCardImageAspectRatio("2:3"); } // fallback to thumb @@ -944,7 +946,7 @@ public class XBMCJsonRPC poster = extractKeyFromArtMap(details, "thumb"); if (poster != null && !poster.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); + med.setCardImageUrl(getImageUrl(poster)); med.setCardImageAspectRatio("16:9"); } } @@ -952,7 +954,7 @@ public class XBMCJsonRPC String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } med.setXbmcUrl("videodb://tvshows/titles/" + details.get("tvshowid").getAsInt() + "/"); med.setCategory(Media.MEDIA_TYPE_TVSHOW); @@ -982,14 +984,14 @@ public class XBMCJsonRPC String thumb = extractKeyFromArtMap(details, "thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("16:9"); } // fanart String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } med.setXbmcUrl("videodb://tvshows/titles/" + details.get("tvshowid").getAsInt() + "/" + details.get("episodeid").getAsInt() + "?showinfo=true"); @@ -1029,14 +1031,14 @@ public class XBMCJsonRPC String thumb = extractKeyFromArtMap(details, "thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("1:1"); } // fanart String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } med.setXbmcUrl("musicdb://albums/" + details.get("albumid").getAsString() + "/"); @@ -1064,7 +1066,7 @@ public class XBMCJsonRPC String thumb = extractKeyFromArtMap(details, "album.thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("1:1"); } // fallback to albumartist.thumb @@ -1073,7 +1075,7 @@ public class XBMCJsonRPC thumb = extractKeyFromArtMap(details, "albumartist.thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("1:1"); } else @@ -1082,7 +1084,7 @@ public class XBMCJsonRPC thumb = extractKeyFromArtMap(details, "artist.thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("1:1"); } } @@ -1091,14 +1093,14 @@ public class XBMCJsonRPC String fanart = extractKeyFromArtMap(details, "albumartist.fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } else { fanart = extractKeyFromArtMap(details, "artist.fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } } @@ -1145,21 +1147,21 @@ public class XBMCJsonRPC String thumb = extractKeyFromArtMap(details, "thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("1:1"); } // fanart String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } med.setXbmcUrl("videodb://musicvideos/titles/" + details.get("musicvideoid").getAsInt()); String url = getDownloadUrl(details.get("file").getAsString()); if (url != null && !url.isEmpty()) - med.setVideoUrl(XBMCFileContentProvider.buildUri(url).toString()); + med.setVideoUrl(getImageUrl(url)); med.setCategory(Media.MEDIA_TYPE_MUSICVIDEO); } @@ -1438,4 +1440,23 @@ public class XBMCJsonRPC return String.valueOf(rating / 2.0); } + private String getImageUrl(String sUrl) + { + Log.d(TAG, "getImageUrl: sUrl = " + sUrl); + if (sUrl.startsWith("image://video@") || sUrl.startsWith("image://music@")) + { + Log.d(TAG, "getImageUrl: " + sUrl + " is not unwrapped"); + return XBMCFileContentProvider.buildUri(sUrl).toString(); + } + + String sUnwrapImageUrl = this.mTextureCache.unwrapImageURL(sUrl); + Log.d(TAG, "getImageUrl: sUnwrapImageUrl = " + sUnwrapImageUrl); + if (!sUnwrapImageUrl.startsWith("http")) + { + return XBMCFileContentProvider.buildUri(sUrl).toString(); + } + + return sUnwrapImageUrl; + } + } diff --git a/tools/android/packaging/xbmc/src/XBMCTextureCache.java.in b/tools/android/packaging/xbmc/src/XBMCTextureCache.java.in new file mode 100644 index 0000000000..09dd7265f5 --- /dev/null +++ b/tools/android/packaging/xbmc/src/XBMCTextureCache.java.in @@ -0,0 +1,32 @@ +package @APP_PACKAGE@; + +import android.util.Log; + +/** + * Created by Maven85 on 16/03/2020. + */ + +public class XBMCTextureCache +{ + native String _unwrapImageURL(String image); + + private static final String TAG = "@APP_NAME@"; + + public XBMCTextureCache() + { + } + + public String unwrapImageURL(String image) + { + try + { + return _unwrapImageURL(image); + } + catch (Exception e) + { + Log.e(TAG, "unwrapImageURL: Exception: " + e.getMessage()); + return null; + } + } + +} diff --git a/xbmc/AutoSwitch.cpp b/xbmc/AutoSwitch.cpp index 14adb8e2bc..0dd710f757 100644 --- a/xbmc/AutoSwitch.cpp +++ b/xbmc/AutoSwitch.cpp @@ -9,6 +9,7 @@ #include "AutoSwitch.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" diff --git a/xbmc/Autorun.cpp b/xbmc/Autorun.cpp index 5d4145ac1b..aad71cf3c8 100644 --- a/xbmc/Autorun.cpp +++ b/xbmc/Autorun.cpp @@ -9,6 +9,7 @@ #include "Autorun.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "GUIUserMessages.h" #include "PlayListPlayer.h" diff --git a/xbmc/BackgroundInfoLoader.cpp b/xbmc/BackgroundInfoLoader.cpp index 55d221ab04..de3d5a3a9e 100644 --- a/xbmc/BackgroundInfoLoader.cpp +++ b/xbmc/BackgroundInfoLoader.cpp @@ -9,6 +9,7 @@ #include "BackgroundInfoLoader.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "threads/Thread.h" #include "utils/log.h" diff --git a/xbmc/CMakeLists.txt b/xbmc/CMakeLists.txt index b7c838b3da..689f4af296 100644 --- a/xbmc/CMakeLists.txt +++ b/xbmc/CMakeLists.txt @@ -8,6 +8,7 @@ set(SOURCES AutoSwitch.cpp DbUrl.cpp DynamicDll.cpp FileItem.cpp + FileItemList.cpp FileItemListModification.cpp GUIInfoManager.cpp GUILargeTextureManager.cpp @@ -45,6 +46,7 @@ set(HEADERS AutoSwitch.h DllPaths_win32.h DynamicDll.h FileItem.h + FileItemList.h FileItemListModification.h GUIInfoManager.h GUILargeTextureManager.h diff --git a/xbmc/CueDocument.cpp b/xbmc/CueDocument.cpp index 674a94aa51..abc5185e63 100644 --- a/xbmc/CueDocument.cpp +++ b/xbmc/CueDocument.cpp @@ -43,6 +43,7 @@ #include "CueDocument.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "Util.h" #include "filesystem/Directory.h" diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp index 2176c3e8e5..558a5a2ad8 100644 --- a/xbmc/FileItem.cpp +++ b/xbmc/FileItem.cpp @@ -9,6 +9,7 @@ #include "FileItem.h" #include "CueDocument.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "Util.h" @@ -17,7 +18,7 @@ #include "filesystem/Directory.h" #include "filesystem/File.h" #include "filesystem/MultiPathDirectory.h" -#include "filesystem/MusicDatabaseDirectory.h" +#include "filesystem/MusicDatabaseDirectory/QueryParams.h" #include "filesystem/StackDirectory.h" #include "filesystem/VideoDatabaseDirectory.h" #include "filesystem/VideoDatabaseDirectory/QueryParams.h" @@ -48,10 +49,8 @@ #include "settings/SettingsComponent.h" #include "settings/lib/Setting.h" #include "utils/Archive.h" -#include "utils/Crc32.h" #include "utils/FileExtensionProvider.h" #include "utils/Mime.h" -#include "utils/Random.h" #include "utils/RegExp.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" @@ -63,10 +62,8 @@ #include "video/VideoInfoTag.h" #include "video/VideoUtils.h" -#include <algorithm> #include <cstdlib> #include <memory> -#include <mutex> using namespace KODI; using namespace KODI::VIDEO; @@ -853,7 +850,7 @@ bool CFileItem::Exists(bool bUseCache /* = true */) const || IsPVR()) return true; - if (IsVideoDb() && HasVideoInfoTag()) + if (IsVideoDb(*this) && HasVideoInfoTag()) { CFileItem dbItem(m_bIsFolder ? GetVideoInfoTag()->m_strPath : GetVideoInfoTag()->m_strFileNameAndPath, m_bIsFolder); return dbItem.Exists(); @@ -915,17 +912,6 @@ bool CFileItem::IsPVRTimer() const return HasPVRTimerInfoTag(); } -bool CFileItem::IsDiscStub() const -{ - if (IsVideoDb() && HasVideoInfoTag()) - { - CFileItem dbItem(m_bIsFolder ? GetVideoInfoTag()->m_strPath : GetVideoInfoTag()->m_strFileNameAndPath, m_bIsFolder); - return dbItem.IsDiscStub(); - } - - return URIUtils::HasExtension(m_strPath, CServiceBroker::GetFileExtensionProvider().GetDiscStubExtensions()); -} - bool CFileItem::IsAudio() const { /* check preset mime type */ @@ -1030,11 +1016,6 @@ bool CFileItem::IsLyrics() const return URIUtils::HasExtension(m_strPath, ".cdg|.lrc"); } -bool CFileItem::IsSubtitle() const -{ - return URIUtils::HasExtension(m_strPath, CServiceBroker::GetFileExtensionProvider().GetSubtitleExtensions()); -} - bool CFileItem::IsCUESheet() const { return URIUtils::HasExtension(m_strPath, ".cue"); @@ -1142,12 +1123,6 @@ bool CFileItem::IsNFO() const return URIUtils::HasExtension(m_strPath, ".nfo"); } -bool CFileItem::IsVideoExtras() const -{ - return m_bIsFolder && - StringUtils::EqualsNoCase(URIUtils::GetFileOrFolderName(m_strPath), "extras"); -} - bool CFileItem::IsDiscImage() const { return URIUtils::IsDiscImage(GetDynPath()); @@ -1155,38 +1130,10 @@ bool CFileItem::IsDiscImage() const bool CFileItem::IsOpticalMediaFile() const { - if (IsDVDFile(false, true)) + if (IsDVDFile(*this, false, true)) return true; - return IsBDFile(); -} - -bool CFileItem::IsDVDFile(bool bVobs /*= true*/, bool bIfos /*= true*/) const -{ - std::string strFileName = URIUtils::GetFileName(GetDynPath()); - if (bIfos) - { - if (StringUtils::EqualsNoCase(strFileName, "video_ts.ifo")) - return true; - if (StringUtils::StartsWithNoCase(strFileName, "vts_") && StringUtils::EndsWithNoCase(strFileName, "_0.ifo") && strFileName.length() == 12) - return true; - } - if (bVobs) - { - if (StringUtils::EqualsNoCase(strFileName, "video_ts.vob")) - return true; - if (StringUtils::StartsWithNoCase(strFileName, "vts_") && StringUtils::EndsWithNoCase(strFileName, ".vob")) - return true; - } - - return false; -} - -bool CFileItem::IsBDFile() const -{ - std::string strFileName = URIUtils::GetFileName(GetDynPath()); - return (StringUtils::EqualsNoCase(strFileName, "index.bdmv") || StringUtils::EqualsNoCase(strFileName, "MovieObject.bdmv") - || StringUtils::EqualsNoCase(strFileName, "INDEX.BDM") || StringUtils::EqualsNoCase(strFileName, "MOVIEOBJ.BDM")); + return IsBDFile(*this); } bool CFileItem::IsRAR() const @@ -1268,17 +1215,7 @@ bool CFileItem::IsBluray() const CFileItem item = CFileItem(VIDEO_UTILS::GetOpticalMediaPath(*this), false); - return item.IsBDFile(); -} - -bool CFileItem::IsProtectedBlurayDisc() const -{ - std::string path; - path = URIUtils::AddFileToFolder(GetPath(), "AACS", "Unit_Key_RO.inf"); - if (CFile::Exists(path)) - return true; - - return false; + return IsBDFile(item); } bool CFileItem::IsCDDA() const @@ -1346,11 +1283,6 @@ bool CFileItem::IsMusicDb() const return URIUtils::IsMusicDb(m_strPath); } -bool CFileItem::IsVideoDb() const -{ - return URIUtils::IsVideoDb(m_strPath); -} - bool CFileItem::IsVirtualDirectoryRoot() const { return (m_bIsFolder && m_strPath.empty()); @@ -1658,7 +1590,7 @@ bool CFileItem::IsSamePath(const CFileItem *item) const dbItem.SetProperty("item_start", GetProperty("item_start")); return dbItem.IsSamePath(item); } - if (IsVideoDb() && HasVideoInfoTag()) + if (IsVideoDb(*this) && HasVideoInfoTag()) { CFileItem dbItem(GetVideoInfoTag()->m_strFileNameAndPath, false); if (HasProperty("item_start")) @@ -1672,7 +1604,7 @@ bool CFileItem::IsSamePath(const CFileItem *item) const dbItem.SetProperty("item_start", item->GetProperty("item_start")); return IsSamePath(&dbItem); } - if (item->IsVideoDb() && item->HasVideoInfoTag()) + if (IsVideoDb(*item) && item->HasVideoInfoTag()) { CFileItem dbItem(item->GetVideoInfoTag()->m_strFileNameAndPath, false); if (item->HasProperty("item_start")) @@ -2122,1083 +2054,6 @@ bool CFileItem::LoadTracksFromCueDocument(CFileItemList& scannedItems) return tracksFound != 0; } -///////////////////////////////////////////////////////////////////////////////// -///// -///// CFileItemList -///// -////////////////////////////////////////////////////////////////////////////////// - -CFileItemList::CFileItemList() -: CFileItem("", true) -{ -} - -CFileItemList::CFileItemList(const std::string& strPath) -: CFileItem(strPath, true) -{ -} - -CFileItemList::~CFileItemList() -{ - Clear(); -} - -CFileItemPtr CFileItemList::operator[] (int iItem) -{ - return Get(iItem); -} - -const CFileItemPtr CFileItemList::operator[] (int iItem) const -{ - return Get(iItem); -} - -CFileItemPtr CFileItemList::operator[] (const std::string& strPath) -{ - return Get(strPath); -} - -const CFileItemPtr CFileItemList::operator[] (const std::string& strPath) const -{ - return Get(strPath); -} - -void CFileItemList::SetIgnoreURLOptions(bool ignoreURLOptions) -{ - m_ignoreURLOptions = ignoreURLOptions; - - if (m_fastLookup) - { - m_fastLookup = false; // Force SetFastlookup to clear map - SetFastLookup(true); // and regenerate map - } -} - -void CFileItemList::SetFastLookup(bool fastLookup) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - - if (fastLookup && !m_fastLookup) - { // generate the map - m_map.clear(); - for (unsigned int i=0; i < m_items.size(); i++) - { - CFileItemPtr pItem = m_items[i]; - m_map.insert(MAPFILEITEMSPAIR(m_ignoreURLOptions ? CURL(pItem->GetPath()).GetWithoutOptions() : pItem->GetPath(), pItem)); - } - } - if (!fastLookup && m_fastLookup) - m_map.clear(); - m_fastLookup = fastLookup; -} - -bool CFileItemList::Contains(const std::string& fileName) const -{ - std::unique_lock<CCriticalSection> lock(m_lock); - - if (m_fastLookup) - return m_map.find(m_ignoreURLOptions ? CURL(fileName).GetWithoutOptions() : fileName) != m_map.end(); - - // slow method... - for (unsigned int i = 0; i < m_items.size(); i++) - { - const CFileItemPtr pItem = m_items[i]; - if (pItem->IsPath(m_ignoreURLOptions ? CURL(fileName).GetWithoutOptions() : fileName)) - return true; - } - return false; -} - -void CFileItemList::Clear() -{ - std::unique_lock<CCriticalSection> lock(m_lock); - - ClearItems(); - m_sortDescription.sortBy = SortByNone; - m_sortDescription.sortOrder = SortOrderNone; - m_sortDescription.sortAttributes = SortAttributeNone; - m_sortIgnoreFolders = false; - m_cacheToDisc = CACHE_IF_SLOW; - m_sortDetails.clear(); - m_replaceListing = false; - m_content.clear(); -} - -void CFileItemList::ClearItems() -{ - std::unique_lock<CCriticalSection> lock(m_lock); - // make sure we free the memory of the items (these are GUIControls which may have allocated resources) - FreeMemory(); - for (unsigned int i = 0; i < m_items.size(); i++) - { - CFileItemPtr item = m_items[i]; - item->FreeMemory(); - } - m_items.clear(); - m_map.clear(); -} - -void CFileItemList::Add(CFileItemPtr pItem) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - if (m_fastLookup) - m_map.insert(MAPFILEITEMSPAIR(m_ignoreURLOptions ? CURL(pItem->GetPath()).GetWithoutOptions() : pItem->GetPath(), pItem)); - m_items.emplace_back(std::move(pItem)); -} - -void CFileItemList::Add(CFileItem&& item) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - auto ptr = std::make_shared<CFileItem>(std::move(item)); - if (m_fastLookup) - m_map.insert(MAPFILEITEMSPAIR(m_ignoreURLOptions ? CURL(ptr->GetPath()).GetWithoutOptions() : ptr->GetPath(), ptr)); - m_items.emplace_back(std::move(ptr)); -} - -void CFileItemList::AddFront(const CFileItemPtr &pItem, int itemPosition) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - - if (itemPosition >= 0) - { - m_items.insert(m_items.begin()+itemPosition, pItem); - } - else - { - m_items.insert(m_items.begin()+(m_items.size()+itemPosition), pItem); - } - if (m_fastLookup) - { - m_map.insert(MAPFILEITEMSPAIR(m_ignoreURLOptions ? CURL(pItem->GetPath()).GetWithoutOptions() : pItem->GetPath(), pItem)); - } -} - -void CFileItemList::Remove(CFileItem* pItem) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - - for (IVECFILEITEMS it = m_items.begin(); it != m_items.end(); ++it) - { - if (pItem == it->get()) - { - m_items.erase(it); - if (m_fastLookup) - { - m_map.erase(m_ignoreURLOptions ? CURL(pItem->GetPath()).GetWithoutOptions() : pItem->GetPath()); - } - break; - } - } -} - -VECFILEITEMS::iterator CFileItemList::erase(VECFILEITEMS::iterator first, - VECFILEITEMS::iterator last) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - return m_items.erase(first, last); -} - -void CFileItemList::Remove(int iItem) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - - if (iItem >= 0 && iItem < Size()) - { - CFileItemPtr pItem = *(m_items.begin() + iItem); - if (m_fastLookup) - { - m_map.erase(m_ignoreURLOptions ? CURL(pItem->GetPath()).GetWithoutOptions() : pItem->GetPath()); - } - m_items.erase(m_items.begin() + iItem); - } -} - -void CFileItemList::Append(const CFileItemList& itemlist) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - - for (int i = 0; i < itemlist.Size(); ++i) - Add(itemlist[i]); -} - -void CFileItemList::Assign(const CFileItemList& itemlist, bool append) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - if (!append) - Clear(); - Append(itemlist); - SetPath(itemlist.GetPath()); - SetLabel(itemlist.GetLabel()); - m_sortDetails = itemlist.m_sortDetails; - m_sortDescription = itemlist.m_sortDescription; - m_replaceListing = itemlist.m_replaceListing; - m_content = itemlist.m_content; - m_mapProperties = itemlist.m_mapProperties; - m_cacheToDisc = itemlist.m_cacheToDisc; -} - -bool CFileItemList::Copy(const CFileItemList& items, bool copyItems /* = true */) -{ - // assign all CFileItem parts - *static_cast<CFileItem*>(this) = static_cast<const CFileItem&>(items); - - // assign the rest of the CFileItemList properties - m_replaceListing = items.m_replaceListing; - m_content = items.m_content; - m_mapProperties = items.m_mapProperties; - m_cacheToDisc = items.m_cacheToDisc; - m_sortDetails = items.m_sortDetails; - m_sortDescription = items.m_sortDescription; - m_sortIgnoreFolders = items.m_sortIgnoreFolders; - - if (copyItems) - { - // make a copy of each item - for (int i = 0; i < items.Size(); i++) - { - CFileItemPtr newItem(new CFileItem(*items[i])); - Add(newItem); - } - } - - return true; -} - -CFileItemPtr CFileItemList::Get(int iItem) const -{ - std::unique_lock<CCriticalSection> lock(m_lock); - - if (iItem > -1 && iItem < (int)m_items.size()) - return m_items[iItem]; - - return CFileItemPtr(); -} - -CFileItemPtr CFileItemList::Get(const std::string& strPath) const -{ - std::unique_lock<CCriticalSection> lock(m_lock); - - if (m_fastLookup) - { - MAPFILEITEMS::const_iterator it = - m_map.find(m_ignoreURLOptions ? CURL(strPath).GetWithoutOptions() : strPath); - if (it != m_map.end()) - return it->second; - - return CFileItemPtr(); - } - // slow method... - for (unsigned int i = 0; i < m_items.size(); i++) - { - CFileItemPtr pItem = m_items[i]; - if (pItem->IsPath(m_ignoreURLOptions ? CURL(strPath).GetWithoutOptions() : strPath)) - return pItem; - } - - return CFileItemPtr(); -} - -int CFileItemList::Size() const -{ - std::unique_lock<CCriticalSection> lock(m_lock); - return (int)m_items.size(); -} - -bool CFileItemList::IsEmpty() const -{ - std::unique_lock<CCriticalSection> lock(m_lock); - return m_items.empty(); -} - -void CFileItemList::Reserve(size_t iCount) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - m_items.reserve(iCount); -} - -void CFileItemList::Sort(FILEITEMLISTCOMPARISONFUNC func) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - std::stable_sort(m_items.begin(), m_items.end(), func); -} - -void CFileItemList::FillSortFields(FILEITEMFILLFUNC func) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - std::for_each(m_items.begin(), m_items.end(), func); -} - -void CFileItemList::Sort(SortBy sortBy, SortOrder sortOrder, SortAttribute sortAttributes /* = SortAttributeNone */) -{ - if (sortBy == SortByNone || - (m_sortDescription.sortBy == sortBy && m_sortDescription.sortOrder == sortOrder && - m_sortDescription.sortAttributes == sortAttributes)) - return; - - SortDescription sorting; - sorting.sortBy = sortBy; - sorting.sortOrder = sortOrder; - sorting.sortAttributes = sortAttributes; - - Sort(sorting); - m_sortDescription = sorting; -} - -void CFileItemList::Sort(SortDescription sortDescription) -{ - if (sortDescription.sortBy == SortByFile || sortDescription.sortBy == SortBySortTitle || - sortDescription.sortBy == SortByOriginalTitle || sortDescription.sortBy == SortByDateAdded || - sortDescription.sortBy == SortByRating || sortDescription.sortBy == SortByYear || - sortDescription.sortBy == SortByPlaylistOrder || sortDescription.sortBy == SortByLastPlayed || - sortDescription.sortBy == SortByPlaycount) - sortDescription.sortAttributes = (SortAttribute)((int)sortDescription.sortAttributes | SortAttributeIgnoreFolders); - - if (sortDescription.sortBy == SortByNone || - (m_sortDescription.sortBy == sortDescription.sortBy && m_sortDescription.sortOrder == sortDescription.sortOrder && - m_sortDescription.sortAttributes == sortDescription.sortAttributes)) - return; - - if (m_sortIgnoreFolders) - sortDescription.sortAttributes = (SortAttribute)((int)sortDescription.sortAttributes | SortAttributeIgnoreFolders); - - const Fields fields = SortUtils::GetFieldsForSorting(sortDescription.sortBy); - SortItems sortItems((size_t)Size()); - for (int index = 0; index < Size(); index++) - { - sortItems[index] = std::make_shared<SortItem>(); - m_items[index]->ToSortable(*sortItems[index], fields); - (*sortItems[index])[FieldId] = index; - } - - // do the sorting - SortUtils::Sort(sortDescription, sortItems); - - // apply the new order to the existing CFileItems - VECFILEITEMS sortedFileItems; - sortedFileItems.reserve(Size()); - for (SortItems::const_iterator it = sortItems.begin(); it != sortItems.end(); ++it) - { - CFileItemPtr item = m_items[(int)(*it)->at(FieldId).asInteger()]; - // Set the sort label in the CFileItem - item->SetSortLabel((*it)->at(FieldSort).asWideString()); - - sortedFileItems.push_back(item); - } - - // replace the current list with the re-ordered one - m_items = std::move(sortedFileItems); -} - -void CFileItemList::Randomize() -{ - std::unique_lock<CCriticalSection> lock(m_lock); - KODI::UTILS::RandomShuffle(m_items.begin(), m_items.end()); -} - -void CFileItemList::Archive(CArchive& ar) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - if (ar.IsStoring()) - { - CFileItem::Archive(ar); - - int i = 0; - if (!m_items.empty() && m_items[0]->IsParentFolder()) - i = 1; - - ar << (int)(m_items.size() - i); - - ar << m_ignoreURLOptions; - - ar << m_fastLookup; - - ar << (int)m_sortDescription.sortBy; - ar << (int)m_sortDescription.sortOrder; - ar << (int)m_sortDescription.sortAttributes; - ar << m_sortIgnoreFolders; - ar << (int)m_cacheToDisc; - - ar << (int)m_sortDetails.size(); - for (unsigned int j = 0; j < m_sortDetails.size(); ++j) - { - const GUIViewSortDetails &details = m_sortDetails[j]; - ar << (int)details.m_sortDescription.sortBy; - ar << (int)details.m_sortDescription.sortOrder; - ar << (int)details.m_sortDescription.sortAttributes; - ar << details.m_buttonLabel; - ar << details.m_labelMasks.m_strLabelFile; - ar << details.m_labelMasks.m_strLabelFolder; - ar << details.m_labelMasks.m_strLabel2File; - ar << details.m_labelMasks.m_strLabel2Folder; - } - - ar << m_content; - - for (; i < (int)m_items.size(); ++i) - { - CFileItemPtr pItem = m_items[i]; - ar << *pItem; - } - } - else - { - CFileItemPtr pParent; - if (!IsEmpty()) - { - CFileItemPtr pItem=m_items[0]; - if (pItem->IsParentFolder()) - pParent = std::make_shared<CFileItem>(*pItem); - } - - SetIgnoreURLOptions(false); - SetFastLookup(false); - Clear(); - - CFileItem::Archive(ar); - - int iSize = 0; - ar >> iSize; - if (iSize <= 0) - return ; - - if (pParent) - { - m_items.reserve(iSize + 1); - m_items.push_back(pParent); - } - else - m_items.reserve(iSize); - - bool ignoreURLOptions = false; - ar >> ignoreURLOptions; - - bool fastLookup = false; - ar >> fastLookup; - - int tempint; - ar >> tempint; - m_sortDescription.sortBy = (SortBy)tempint; - ar >> tempint; - m_sortDescription.sortOrder = (SortOrder)tempint; - ar >> tempint; - m_sortDescription.sortAttributes = (SortAttribute)tempint; - ar >> m_sortIgnoreFolders; - ar >> tempint; - m_cacheToDisc = CACHE_TYPE(tempint); - - unsigned int detailSize = 0; - ar >> detailSize; - for (unsigned int j = 0; j < detailSize; ++j) - { - GUIViewSortDetails details; - ar >> tempint; - details.m_sortDescription.sortBy = (SortBy)tempint; - ar >> tempint; - details.m_sortDescription.sortOrder = (SortOrder)tempint; - ar >> tempint; - details.m_sortDescription.sortAttributes = (SortAttribute)tempint; - ar >> details.m_buttonLabel; - ar >> details.m_labelMasks.m_strLabelFile; - ar >> details.m_labelMasks.m_strLabelFolder; - ar >> details.m_labelMasks.m_strLabel2File; - ar >> details.m_labelMasks.m_strLabel2Folder; - m_sortDetails.push_back(details); - } - - ar >> m_content; - - for (int i = 0; i < iSize; ++i) - { - CFileItemPtr pItem(new CFileItem); - ar >> *pItem; - Add(pItem); - } - - SetIgnoreURLOptions(ignoreURLOptions); - SetFastLookup(fastLookup); - } -} - -void CFileItemList::FillInDefaultIcons() -{ - std::unique_lock<CCriticalSection> lock(m_lock); - for (int i = 0; i < (int)m_items.size(); ++i) - { - CFileItemPtr pItem = m_items[i]; - pItem->FillInDefaultIcon(); - } -} - -int CFileItemList::GetFolderCount() const -{ - std::unique_lock<CCriticalSection> lock(m_lock); - int nFolderCount = 0; - for (int i = 0; i < (int)m_items.size(); i++) - { - CFileItemPtr pItem = m_items[i]; - if (pItem->m_bIsFolder) - nFolderCount++; - } - - return nFolderCount; -} - -int CFileItemList::GetObjectCount() const -{ - std::unique_lock<CCriticalSection> lock(m_lock); - - int numObjects = (int)m_items.size(); - if (numObjects && m_items[0]->IsParentFolder()) - numObjects--; - - return numObjects; -} - -int CFileItemList::GetFileCount() const -{ - std::unique_lock<CCriticalSection> lock(m_lock); - int nFileCount = 0; - for (int i = 0; i < (int)m_items.size(); i++) - { - CFileItemPtr pItem = m_items[i]; - if (!pItem->m_bIsFolder) - nFileCount++; - } - - return nFileCount; -} - -int CFileItemList::GetSelectedCount() const -{ - std::unique_lock<CCriticalSection> lock(m_lock); - int count = 0; - for (int i = 0; i < (int)m_items.size(); i++) - { - CFileItemPtr pItem = m_items[i]; - if (pItem->IsSelected()) - count++; - } - - return count; -} - -void CFileItemList::FilterCueItems() -{ - std::unique_lock<CCriticalSection> lock(m_lock); - // Handle .CUE sheet files... - std::vector<std::string> itemstodelete; - for (int i = 0; i < (int)m_items.size(); i++) - { - CFileItemPtr pItem = m_items[i]; - if (!pItem->m_bIsFolder) - { // see if it's a .CUE sheet - if (pItem->IsCUESheet()) - { - CCueDocumentPtr cuesheet(new CCueDocument); - if (cuesheet->ParseFile(pItem->GetPath())) - { - std::vector<std::string> MediaFileVec; - cuesheet->GetMediaFiles(MediaFileVec); - - // queue the cue sheet and the underlying media file for deletion - for (std::vector<std::string>::iterator itMedia = MediaFileVec.begin(); - itMedia != MediaFileVec.end(); ++itMedia) - { - std::string strMediaFile = *itMedia; - std::string fileFromCue = strMediaFile; // save the file from the cue we're matching against, - // as we're going to search for others here... - bool bFoundMediaFile = CFile::Exists(strMediaFile); - if (!bFoundMediaFile) - { - // try file in same dir, not matching case... - if (Contains(strMediaFile)) - { - bFoundMediaFile = true; - } - else - { - // try removing the .cue extension... - strMediaFile = pItem->GetPath(); - URIUtils::RemoveExtension(strMediaFile); - CFileItem item(strMediaFile, false); - if (item.IsAudio() && Contains(strMediaFile)) - { - bFoundMediaFile = true; - } - else - { // try replacing the extension with one of our allowed ones. - std::vector<std::string> extensions = StringUtils::Split(CServiceBroker::GetFileExtensionProvider().GetMusicExtensions(), "|"); - for (std::vector<std::string>::const_iterator i = extensions.begin(); i != extensions.end(); ++i) - { - strMediaFile = URIUtils::ReplaceExtension(pItem->GetPath(), *i); - CFileItem item(strMediaFile, false); - if (!item.IsCUESheet() && !item.IsPlayList() && Contains(strMediaFile)) - { - bFoundMediaFile = true; - break; - } - } - } - } - } - if (bFoundMediaFile) - { - cuesheet->UpdateMediaFile(fileFromCue, strMediaFile); - // apply CUE for later processing - for (int j = 0; j < (int)m_items.size(); j++) - { - CFileItemPtr pItem = m_items[j]; - if (StringUtils::CompareNoCase(pItem->GetPath(), strMediaFile) == 0) - pItem->SetCueDocument(cuesheet); - } - } - } - } - itemstodelete.push_back(pItem->GetPath()); - } - } - } - // now delete the .CUE files. - for (int i = 0; i < (int)itemstodelete.size(); i++) - { - for (int j = 0; j < (int)m_items.size(); j++) - { - CFileItemPtr pItem = m_items[j]; - if (StringUtils::CompareNoCase(pItem->GetPath(), itemstodelete[i]) == 0) - { // delete this item - m_items.erase(m_items.begin() + j); - break; - } - } - } -} - -// Remove the extensions from the filenames -void CFileItemList::RemoveExtensions() -{ - std::unique_lock<CCriticalSection> lock(m_lock); - for (int i = 0; i < Size(); ++i) - m_items[i]->RemoveExtension(); -} - -void CFileItemList::Stack(bool stackFiles /* = true */) -{ - std::unique_lock<CCriticalSection> lock(m_lock); - - // not allowed here - if (IsVirtualDirectoryRoot() || - IsLiveTV() || - IsSourcesPath() || - IsLibraryFolder()) - return; - - SetProperty("isstacked", true); - - // items needs to be sorted for stuff below to work properly - Sort(SortByLabel, SortOrderAscending); - - StackFolders(); - - if (stackFiles) - StackFiles(); -} - -void CFileItemList::StackFolders() -{ - // Precompile our REs - VECCREGEXP folderRegExps; - CRegExp folderRegExp(true, CRegExp::autoUtf8); - const std::vector<std::string>& strFolderRegExps = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_folderStackRegExps; - - std::vector<std::string>::const_iterator strExpression = strFolderRegExps.begin(); - while (strExpression != strFolderRegExps.end()) - { - if (!folderRegExp.RegComp(*strExpression)) - CLog::Log(LOGERROR, "{}: Invalid folder stack RegExp:'{}'", __FUNCTION__, - strExpression->c_str()); - else - folderRegExps.push_back(folderRegExp); - - ++strExpression; - } - - if (!folderRegExp.IsCompiled()) - { - CLog::Log(LOGDEBUG, "{}: No stack expressions available. Skipping folder stacking", - __FUNCTION__); - return; - } - - // stack folders - for (int i = 0; i < Size(); i++) - { - CFileItemPtr item = Get(i); - // combined the folder checks - if (item->m_bIsFolder) - { - // only check known fast sources? - // NOTES: - // 1. rars and zips may be on slow sources? is this supposed to be allowed? - if( !item->IsRemote() - || item->IsSmb() - || item->IsNfs() - || URIUtils::IsInRAR(item->GetPath()) - || URIUtils::IsInZIP(item->GetPath()) - || URIUtils::IsOnLAN(item->GetPath()) - ) - { - // stack cd# folders if contains only a single video file - - bool bMatch(false); - - VECCREGEXP::iterator expr = folderRegExps.begin(); - while (!bMatch && expr != folderRegExps.end()) - { - //CLog::Log(LOGDEBUG,"{}: Running expression {} on {}", __FUNCTION__, expr->GetPattern(), item->GetLabel()); - bMatch = (expr->RegFind(item->GetLabel().c_str()) != -1); - if (bMatch) - { - CFileItemList items; - CDirectory::GetDirectory(item->GetPath(), items, - CServiceBroker::GetFileExtensionProvider().GetVideoExtensions(), - DIR_FLAG_DEFAULTS); - // optimized to only traverse listing once by checking for filecount - // and recording last file item for later use - int nFiles = 0; - int index = -1; - for (int j = 0; j < items.Size(); j++) - { - if (!items[j]->m_bIsFolder) - { - nFiles++; - index = j; - } - - if (nFiles > 1) - break; - } - - if (nFiles == 1) - *item = *items[index]; - } - ++expr; - } - - // check for dvd folders - if (!bMatch) - { - std::string dvdPath = VIDEO_UTILS::GetOpticalMediaPath(*item); - - if (!dvdPath.empty()) - { - // NOTE: should this be done for the CD# folders too? - item->m_bIsFolder = false; - item->SetPath(dvdPath); - item->SetLabel2(""); - item->SetLabelPreformatted(true); - m_sortDescription.sortBy = SortByNone; /* sorting is now broken */ - } - } - } - } - } -} - -void CFileItemList::StackFiles() -{ - // Precompile our REs - VECCREGEXP stackRegExps; - CRegExp tmpRegExp(true, CRegExp::autoUtf8); - const std::vector<std::string>& strStackRegExps = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoStackRegExps; - std::vector<std::string>::const_iterator strRegExp = strStackRegExps.begin(); - while (strRegExp != strStackRegExps.end()) - { - if (tmpRegExp.RegComp(*strRegExp)) - { - if (tmpRegExp.GetCaptureTotal() == 4) - stackRegExps.push_back(tmpRegExp); - else - CLog::Log(LOGERROR, "Invalid video stack RE ({}). Must have 4 captures.", *strRegExp); - } - ++strRegExp; - } - - // now stack the files, some of which may be from the previous stack iteration - int i = 0; - while (i < Size()) - { - CFileItemPtr item1 = Get(i); - - // skip folders, nfo files, playlists - if (item1->m_bIsFolder - || item1->IsParentFolder() - || item1->IsNFO() - || item1->IsPlayList() - ) - { - // increment index - i++; - continue; - } - - int64_t size = 0; - size_t offset = 0; - std::string stackName; - std::string file1; - std::string filePath; - std::vector<int> stack; - VECCREGEXP::iterator expr = stackRegExps.begin(); - - URIUtils::Split(item1->GetPath(), filePath, file1); - if (URIUtils::HasEncodedFilename(CURL(filePath))) - file1 = CURL::Decode(file1); - - int j; - while (expr != stackRegExps.end()) - { - if (expr->RegFind(file1, offset) != -1) - { - std::string Title1 = expr->GetMatch(1), - Volume1 = expr->GetMatch(2), - Ignore1 = expr->GetMatch(3), - Extension1 = expr->GetMatch(4); - if (offset) - Title1 = file1.substr(0, expr->GetSubStart(2)); - j = i + 1; - while (j < Size()) - { - CFileItemPtr item2 = Get(j); - - // skip folders, nfo files, playlists - if (item2->m_bIsFolder - || item2->IsParentFolder() - || item2->IsNFO() - || item2->IsPlayList() - ) - { - // increment index - j++; - continue; - } - - std::string file2, filePath2; - URIUtils::Split(item2->GetPath(), filePath2, file2); - if (URIUtils::HasEncodedFilename(CURL(filePath2)) ) - file2 = CURL::Decode(file2); - - if (expr->RegFind(file2, offset) != -1) - { - std::string Title2 = expr->GetMatch(1), - Volume2 = expr->GetMatch(2), - Ignore2 = expr->GetMatch(3), - Extension2 = expr->GetMatch(4); - if (offset) - Title2 = file2.substr(0, expr->GetSubStart(2)); - if (StringUtils::EqualsNoCase(Title1, Title2)) - { - if (!StringUtils::EqualsNoCase(Volume1, Volume2)) - { - if (StringUtils::EqualsNoCase(Ignore1, Ignore2) && - StringUtils::EqualsNoCase(Extension1, Extension2)) - { - if (stack.empty()) - { - stackName = Title1 + Ignore1 + Extension1; - stack.push_back(i); - size += item1->m_dwSize; - } - stack.push_back(j); - size += item2->m_dwSize; - } - else // Sequel - { - offset = 0; - ++expr; - break; - } - } - else if (!StringUtils::EqualsNoCase(Ignore1, Ignore2)) // False positive, try again with offset - { - offset = expr->GetSubStart(3); - break; - } - else // Extension mismatch - { - offset = 0; - ++expr; - break; - } - } - else // Title mismatch - { - offset = 0; - ++expr; - break; - } - } - else // No match 2, next expression - { - offset = 0; - ++expr; - break; - } - j++; - } - if (j == Size()) - expr = stackRegExps.end(); - } - else // No match 1 - { - offset = 0; - ++expr; - } - if (stack.size() > 1) - { - // have a stack, remove the items and add the stacked item - // dont actually stack a multipart rar set, just remove all items but the first - std::string stackPath; - if (Get(stack[0])->IsRAR()) - stackPath = Get(stack[0])->GetPath(); - else - { - CStackDirectory dir; - stackPath = dir.ConstructStackPath(*this, stack); - } - item1->SetPath(stackPath); - // clean up list - for (unsigned k = 1; k < stack.size(); k++) - Remove(i+1); - // item->m_bIsFolder = true; // don't treat stacked files as folders - // the label may be in a different char set from the filename (eg over smb - // the label is converted from utf8, but the filename is not) - if (!CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_FILELISTS_SHOWEXTENSIONS)) - URIUtils::RemoveExtension(stackName); - - item1->SetLabel(stackName); - item1->m_dwSize = size; - break; - } - } - i++; - } -} - -bool CFileItemList::Load(int windowID) -{ - CFile file; - auto path = GetDiscFileCache(windowID); - try - { - if (file.Open(path)) - { - CArchive ar(&file, CArchive::load); - ar >> *this; - CLog::Log(LOGDEBUG, "Loading items: {}, directory: {} sort method: {}, ascending: {}", Size(), - CURL::GetRedacted(GetPath()), m_sortDescription.sortBy, - m_sortDescription.sortOrder == SortOrderAscending ? "true" : "false"); - ar.Close(); - file.Close(); - return true; - } - } - catch(const std::out_of_range&) - { - CLog::Log(LOGERROR, "Corrupt archive: {}", CURL::GetRedacted(path)); - } - - return false; -} - -bool CFileItemList::Save(int windowID) -{ - int iSize = Size(); - if (iSize <= 0) - return false; - - CLog::Log(LOGDEBUG, "Saving fileitems [{}]", CURL::GetRedacted(GetPath())); - - CFile file; - std::string cachefile = GetDiscFileCache(windowID); - if (file.OpenForWrite(cachefile, true)) // overwrite always - { - // Before caching save simplified cache file name in every item so the cache file can be - // identifed and removed if the item is updated. List path and options (used for file - // name when list cached) can not be accurately derived from item path. - StringUtils::Replace(cachefile, "special://temp/archive_cache/", ""); - StringUtils::Replace(cachefile, ".fi", ""); - for (const auto& item : m_items) - item->SetProperty("cachefilename", cachefile); - - CArchive ar(&file, CArchive::store); - ar << *this; - CLog::Log(LOGDEBUG, " -- items: {}, sort method: {}, ascending: {}", iSize, - m_sortDescription.sortBy, - m_sortDescription.sortOrder == SortOrderAscending ? "true" : "false"); - ar.Close(); - file.Close(); - return true; - } - - return false; -} - -void CFileItemList::RemoveDiscCache(int windowID) const -{ - RemoveDiscCache(GetDiscFileCache(windowID)); -} - -void CFileItemList::RemoveDiscCache(const std::string& cacheFile) const -{ - if (CFile::Exists(cacheFile)) - { - CLog::Log(LOGDEBUG, "Clearing cached fileitems [{}]", CURL::GetRedacted(GetPath())); - CFile::Delete(cacheFile); - } -} - -void CFileItemList::RemoveDiscCacheCRC(const std::string& crc) const -{ - std::string cachefile = StringUtils::Format("special://temp/archive_cache/{}.fi", crc); - RemoveDiscCache(cachefile); -} - -std::string CFileItemList::GetDiscFileCache(int windowID) const -{ - std::string strPath(GetPath()); - URIUtils::RemoveSlashAtEnd(strPath); - - uint32_t crc = Crc32::ComputeFromLowerCase(strPath); - - if (IsCDDA() || IsOnDVD()) - return StringUtils::Format("special://temp/archive_cache/r-{:08x}.fi", crc); - - if (IsMusicDb()) - return StringUtils::Format("special://temp/archive_cache/mdb-{:08x}.fi", crc); - - if (IsVideoDb()) - return StringUtils::Format("special://temp/archive_cache/vdb-{:08x}.fi", crc); - - if (IsSmartPlayList()) - return StringUtils::Format("special://temp/archive_cache/sp-{:08x}.fi", crc); - - if (windowID) - return StringUtils::Format("special://temp/archive_cache/{}-{:08x}.fi", windowID, crc); - - return StringUtils::Format("special://temp/archive_cache/{:08x}.fi", crc); -} - -bool CFileItemList::AlwaysCache() const -{ - // some database folders are always cached - if (IsMusicDb()) - return CMusicDatabaseDirectory::CanCache(GetPath()); - if (IsVideoDb()) - return CVideoDatabaseDirectory::CanCache(GetPath()); - if (IsEPG()) - return true; // always cache - return false; -} - std::string CFileItem::GetUserMusicThumb(bool alwaysCheckRemote /* = false */, bool fallbackToFolder /* = false */) const { if (m_strPath.empty() @@ -3532,7 +2387,7 @@ std::string CFileItem::GetBaseMoviePath(bool bUseFolderNames) const std::string CFileItem::GetLocalFanart() const { - if (IsVideoDb()) + if (IsVideoDb(*this)) { if (!HasVideoInfoTag()) return ""; // nothing can be done @@ -3706,7 +2561,7 @@ bool CFileItem::LoadGameTag() bool CFileItem::LoadDetails() { - if (IsVideoDb()) + if (IsVideoDb(*this)) { if (HasVideoInfoTag()) return true; @@ -3886,66 +2741,6 @@ bool CFileItem::LoadDetails() return false; } -void CFileItemList::Swap(unsigned int item1, unsigned int item2) -{ - if (item1 != item2 && item1 < m_items.size() && item2 < m_items.size()) - std::swap(m_items[item1], m_items[item2]); -} - -bool CFileItemList::UpdateItem(const CFileItem *item) -{ - if (!item) - return false; - - std::unique_lock<CCriticalSection> lock(m_lock); - for (unsigned int i = 0; i < m_items.size(); i++) - { - CFileItemPtr pItem = m_items[i]; - if (pItem->IsSamePath(item)) - { - pItem->UpdateInfo(*item); - return true; - } - } - return false; -} - -void CFileItemList::AddSortMethod(SortBy sortBy, int buttonLabel, const LABEL_MASKS &labelMasks, SortAttribute sortAttributes /* = SortAttributeNone */) -{ - AddSortMethod(sortBy, sortAttributes, buttonLabel, labelMasks); -} - -void CFileItemList::AddSortMethod(SortBy sortBy, SortAttribute sortAttributes, int buttonLabel, const LABEL_MASKS &labelMasks) -{ - SortDescription sorting; - sorting.sortBy = sortBy; - sorting.sortAttributes = sortAttributes; - - AddSortMethod(sorting, buttonLabel, labelMasks); -} - -void CFileItemList::AddSortMethod(SortDescription sortDescription, int buttonLabel, const LABEL_MASKS &labelMasks) -{ - GUIViewSortDetails sort; - sort.m_sortDescription = sortDescription; - sort.m_buttonLabel = buttonLabel; - sort.m_labelMasks = labelMasks; - - m_sortDetails.push_back(sort); -} - -void CFileItemList::SetReplaceListing(bool replace) -{ - m_replaceListing = replace; -} - -void CFileItemList::ClearSortState() -{ - m_sortDescription.sortBy = SortByNone; - m_sortDescription.sortOrder = SortOrderNone; - m_sortDescription.sortAttributes = SortAttributeNone; -} - bool CFileItem::HasVideoInfoTag() const { // Note: CPVRRecording is derived from CVideoInfoTag diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h index 972601c317..473c11c9d7 100644 --- a/xbmc/FileItem.h +++ b/xbmc/FileItem.h @@ -156,8 +156,6 @@ public: bool Exists(bool bUseCache = true) const; - bool IsDiscStub() const; - /*! \brief Check whether an item is a picture item. Note that this returns true for anything with a picture info tag, so that may include eg. folders. @@ -165,7 +163,6 @@ public: */ bool IsPicture() const; bool IsLyrics() const; - bool IsSubtitle() const; /*! \brief Check whether an item is an audio item. Note that this returns true for @@ -199,13 +196,9 @@ public: bool IsAddonsPath() const; bool IsSourcesPath() const; bool IsNFO() const; - bool IsVideoExtras() const; bool IsDiscImage() const; bool IsOpticalMediaFile() const; - bool IsDVDFile(bool bVobs = true, bool bIfos = true) const; - bool IsBDFile() const; bool IsBluray() const; - bool IsProtectedBlurayDisc() const; bool IsRAR() const; bool IsAPK() const; bool IsZIP() const; @@ -225,7 +218,6 @@ public: bool IsFavourite() const; bool IsMultiPath() const; bool IsMusicDb() const; - bool IsVideoDb() const; bool IsEPG() const; bool IsPVRChannel() const; bool IsPVRChannelGroup() const; @@ -618,6 +610,7 @@ public: void LoadEmbeddedCue(); bool HasCueDocument() const; bool LoadTracksFromCueDocument(CFileItemList& scannedItems); + private: /*! \brief initialize all members of this class (not CGUIListItem members) to default values. Called from constructors, and from Reset() @@ -701,181 +694,4 @@ typedef std::map<std::string, CFileItemPtr > MAPFILEITEMS; typedef std::pair<std::string, CFileItemPtr > MAPFILEITEMSPAIR; typedef bool (*FILEITEMLISTCOMPARISONFUNC) (const CFileItemPtr &pItem1, const CFileItemPtr &pItem2); -typedef void (*FILEITEMFILLFUNC) (CFileItemPtr &item); - -/*! - \brief Represents a list of files - \sa CFileItemList, CFileItem - */ -class CFileItemList : public CFileItem -{ -public: - enum CACHE_TYPE { CACHE_NEVER = 0, CACHE_IF_SLOW, CACHE_ALWAYS }; - - CFileItemList(); - explicit CFileItemList(const std::string& strPath); - ~CFileItemList() override; - void Archive(CArchive& ar) override; - CFileItemPtr operator[] (int iItem); - const CFileItemPtr operator[] (int iItem) const; - CFileItemPtr operator[] (const std::string& strPath); - const CFileItemPtr operator[] (const std::string& strPath) const; - void Clear(); - void ClearItems(); - void Add(CFileItemPtr item); - void Add(CFileItem&& item); - void AddFront(const CFileItemPtr &pItem, int itemPosition); - void Remove(CFileItem* pItem); - void Remove(int iItem); - CFileItemPtr Get(int iItem) const; - const VECFILEITEMS& GetList() const { return m_items; } - CFileItemPtr Get(const std::string& strPath) const; - int Size() const; - bool IsEmpty() const; - void Append(const CFileItemList& itemlist); - void Assign(const CFileItemList& itemlist, bool append = false); - bool Copy (const CFileItemList& item, bool copyItems = true); - void Reserve(size_t iCount); - void Sort(SortBy sortBy, SortOrder sortOrder, SortAttribute sortAttributes = SortAttributeNone); - /* \brief Sorts the items based on the given sorting options - - In contrast to Sort (see above) this does not change the internal - state by storing the sorting method and order used and therefore - will always execute the sorting even if the list of items has - already been sorted with the same options before. - */ - void Sort(SortDescription sortDescription); - void Randomize(); - void FillInDefaultIcons(); - int GetFolderCount() const; - int GetFileCount() const; - int GetSelectedCount() const; - int GetObjectCount() const; - void FilterCueItems(); - void RemoveExtensions(); - void SetIgnoreURLOptions(bool ignoreURLOptions); - void SetFastLookup(bool fastLookup); - bool Contains(const std::string& fileName) const; - bool GetFastLookup() const { return m_fastLookup; } - - /*! \brief stack a CFileItemList - By default we stack all items (files and folders) in a CFileItemList - \param stackFiles whether to stack all items or just collapse folders (defaults to true) - \sa StackFiles,StackFolders - */ - void Stack(bool stackFiles = true); - - SortOrder GetSortOrder() const { return m_sortDescription.sortOrder; } - SortBy GetSortMethod() const { return m_sortDescription.sortBy; } - void SetSortOrder(SortOrder sortOrder) { m_sortDescription.sortOrder = sortOrder; } - void SetSortMethod(SortBy sortBy) { m_sortDescription.sortBy = sortBy; } - - /*! \brief load a CFileItemList out of the cache - - The file list may be cached based on which window we're viewing in, as different - windows will be listing different portions of the same URL (eg viewing music files - versus viewing video files) - - \param windowID id of the window that's loading this list (defaults to 0) - \return true if we loaded from the cache, false otherwise. - \sa Save,RemoveDiscCache - */ - bool Load(int windowID = 0); - - /*! \brief save a CFileItemList to the cache - - The file list may be cached based on which window we're viewing in, as different - windows will be listing different portions of the same URL (eg viewing music files - versus viewing video files) - - \param windowID id of the window that's saving this list (defaults to 0) - \return true if successful, false otherwise. - \sa Load,RemoveDiscCache - */ - bool Save(int windowID = 0); - void SetCacheToDisc(CACHE_TYPE cacheToDisc) { m_cacheToDisc = cacheToDisc; } - bool CacheToDiscAlways() const { return m_cacheToDisc == CACHE_ALWAYS; } - bool CacheToDiscIfSlow() const { return m_cacheToDisc == CACHE_IF_SLOW; } - /*! \brief remove a previously cached CFileItemList from the cache - - The file list may be cached based on which window we're viewing in, as different - windows will be listing different portions of the same URL (eg viewing music files - versus viewing video files) - - \param windowID id of the window whose cache we which to remove (defaults to 0) - \sa Save,Load - */ - void RemoveDiscCache(int windowID = 0) const; - void RemoveDiscCache(const std::string& cachefile) const; - void RemoveDiscCacheCRC(const std::string& crc) const; - bool AlwaysCache() const; - - void Swap(unsigned int item1, unsigned int item2); - - /*! \brief Update an item in the item list - \param item the new item, which we match based on path to an existing item in the list - \return true if the item exists in the list (and was thus updated), false otherwise. - */ - bool UpdateItem(const CFileItem *item); - - void AddSortMethod(SortBy sortBy, int buttonLabel, const LABEL_MASKS &labelMasks, SortAttribute sortAttributes = SortAttributeNone); - void AddSortMethod(SortBy sortBy, SortAttribute sortAttributes, int buttonLabel, const LABEL_MASKS &labelMasks); - void AddSortMethod(SortDescription sortDescription, int buttonLabel, const LABEL_MASKS &labelMasks); - bool HasSortDetails() const { return m_sortDetails.size() != 0; } - const std::vector<GUIViewSortDetails> &GetSortDetails() const { return m_sortDetails; } - - /*! \brief Specify whether this list should be sorted with folders separate from files - By default we sort with folders listed (and sorted separately) except for those sort modes - which should be explicitly sorted with folders interleaved with files (eg SORT_METHOD_FILES). - With this set the folder state will be ignored, allowing folders and files to sort interleaved. - \param sort whether to ignore the folder state. - */ - void SetSortIgnoreFolders(bool sort) { m_sortIgnoreFolders = sort; } - bool GetReplaceListing() const { return m_replaceListing; } - void SetReplaceListing(bool replace); - void SetContent(const std::string& content) { m_content = content; } - const std::string& GetContent() const { return m_content; } - - void ClearSortState(); - - VECFILEITEMS::iterator begin() { return m_items.begin(); } - VECFILEITEMS::iterator end() { return m_items.end(); } - VECFILEITEMS::iterator erase(VECFILEITEMS::iterator first, VECFILEITEMS::iterator last); - VECFILEITEMS::const_iterator begin() const { return m_items.begin(); } - VECFILEITEMS::const_iterator end() const { return m_items.end(); } - VECFILEITEMS::const_iterator cbegin() const { return m_items.cbegin(); } - VECFILEITEMS::const_iterator cend() const { return m_items.cend(); } - std::reverse_iterator<VECFILEITEMS::const_iterator> rbegin() const { return m_items.rbegin(); } - std::reverse_iterator<VECFILEITEMS::const_iterator> rend() const { return m_items.rend(); } - -private: - void Sort(FILEITEMLISTCOMPARISONFUNC func); - void FillSortFields(FILEITEMFILLFUNC func); - std::string GetDiscFileCache(int windowID) const; - - /*! - \brief stack files in a CFileItemList - \sa Stack - */ - void StackFiles(); - - /*! - \brief stack folders in a CFileItemList - \sa Stack - */ - void StackFolders(); - - VECFILEITEMS m_items; - MAPFILEITEMS m_map; - bool m_ignoreURLOptions = false; - bool m_fastLookup = false; - SortDescription m_sortDescription; - bool m_sortIgnoreFolders = false; - CACHE_TYPE m_cacheToDisc = CACHE_IF_SLOW; - bool m_replaceListing = false; - std::string m_content; - - std::vector<GUIViewSortDetails> m_sortDetails; - - mutable CCriticalSection m_lock; -}; +typedef void (*FILEITEMFILLFUNC)(CFileItemPtr& item); diff --git a/xbmc/FileItemList.cpp b/xbmc/FileItemList.cpp new file mode 100644 index 0000000000..0ba0abbc8c --- /dev/null +++ b/xbmc/FileItemList.cpp @@ -0,0 +1,1174 @@ +/* + * Copyright (C) 2005-2020 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 "FileItemList.h" + +#include "CueDocument.h" +#include "ServiceBroker.h" +#include "URL.h" +#include "filesystem/Directory.h" +#include "filesystem/File.h" +#include "filesystem/MusicDatabaseDirectory.h" +#include "filesystem/StackDirectory.h" +#include "filesystem/VideoDatabaseDirectory.h" +#include "settings/AdvancedSettings.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "utils/Archive.h" +#include "utils/Crc32.h" +#include "utils/FileExtensionProvider.h" +#include "utils/Random.h" +#include "utils/RegExp.h" +#include "utils/URIUtils.h" +#include "utils/log.h" +#include "video/VideoFileItemClassify.h" +#include "video/VideoUtils.h" + +#include <algorithm> + +using namespace KODI; +using namespace XFILE; + +CFileItemList::CFileItemList() : CFileItem("", true) +{ +} + +CFileItemList::CFileItemList(const std::string& strPath) : CFileItem(strPath, true) +{ +} + +CFileItemList::~CFileItemList() +{ + Clear(); +} + +CFileItemPtr CFileItemList::operator[](int iItem) +{ + return Get(iItem); +} + +const CFileItemPtr CFileItemList::operator[](int iItem) const +{ + return Get(iItem); +} + +CFileItemPtr CFileItemList::operator[](const std::string& strPath) +{ + return Get(strPath); +} + +const CFileItemPtr CFileItemList::operator[](const std::string& strPath) const +{ + return Get(strPath); +} + +void CFileItemList::SetIgnoreURLOptions(bool ignoreURLOptions) +{ + m_ignoreURLOptions = ignoreURLOptions; + + if (m_fastLookup) + { + m_fastLookup = false; // Force SetFastlookup to clear map + SetFastLookup(true); // and regenerate map + } +} + +void CFileItemList::SetFastLookup(bool fastLookup) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + + if (fastLookup && !m_fastLookup) + { // generate the map + m_map.clear(); + for (unsigned int i = 0; i < m_items.size(); i++) + { + CFileItemPtr pItem = m_items[i]; + m_map.insert(MAPFILEITEMSPAIR(m_ignoreURLOptions ? CURL(pItem->GetPath()).GetWithoutOptions() + : pItem->GetPath(), + pItem)); + } + } + if (!fastLookup && m_fastLookup) + m_map.clear(); + m_fastLookup = fastLookup; +} + +bool CFileItemList::Contains(const std::string& fileName) const +{ + std::unique_lock<CCriticalSection> lock(m_lock); + + if (m_fastLookup) + return m_map.find(m_ignoreURLOptions ? CURL(fileName).GetWithoutOptions() : fileName) != + m_map.end(); + + // slow method... + for (unsigned int i = 0; i < m_items.size(); i++) + { + const CFileItemPtr pItem = m_items[i]; + if (pItem->IsPath(m_ignoreURLOptions ? CURL(fileName).GetWithoutOptions() : fileName)) + return true; + } + return false; +} + +void CFileItemList::Clear() +{ + std::unique_lock<CCriticalSection> lock(m_lock); + + ClearItems(); + m_sortDescription.sortBy = SortByNone; + m_sortDescription.sortOrder = SortOrderNone; + m_sortDescription.sortAttributes = SortAttributeNone; + m_sortIgnoreFolders = false; + m_cacheToDisc = CACHE_IF_SLOW; + m_sortDetails.clear(); + m_replaceListing = false; + m_content.clear(); +} + +void CFileItemList::ClearItems() +{ + std::unique_lock<CCriticalSection> lock(m_lock); + // make sure we free the memory of the items (these are GUIControls which may have allocated resources) + FreeMemory(); + for (unsigned int i = 0; i < m_items.size(); i++) + { + CFileItemPtr item = m_items[i]; + item->FreeMemory(); + } + m_items.clear(); + m_map.clear(); +} + +void CFileItemList::Add(CFileItemPtr pItem) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + if (m_fastLookup) + m_map.insert(MAPFILEITEMSPAIR( + m_ignoreURLOptions ? CURL(pItem->GetPath()).GetWithoutOptions() : pItem->GetPath(), pItem)); + m_items.emplace_back(std::move(pItem)); +} + +void CFileItemList::Add(CFileItem&& item) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + auto ptr = std::make_shared<CFileItem>(std::move(item)); + if (m_fastLookup) + m_map.insert(MAPFILEITEMSPAIR( + m_ignoreURLOptions ? CURL(ptr->GetPath()).GetWithoutOptions() : ptr->GetPath(), ptr)); + m_items.emplace_back(std::move(ptr)); +} + +void CFileItemList::AddFront(const CFileItemPtr& pItem, int itemPosition) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + + if (itemPosition >= 0) + { + m_items.insert(m_items.begin() + itemPosition, pItem); + } + else + { + m_items.insert(m_items.begin() + (m_items.size() + itemPosition), pItem); + } + if (m_fastLookup) + { + m_map.insert(MAPFILEITEMSPAIR( + m_ignoreURLOptions ? CURL(pItem->GetPath()).GetWithoutOptions() : pItem->GetPath(), pItem)); + } +} + +void CFileItemList::Remove(CFileItem* pItem) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + + for (IVECFILEITEMS it = m_items.begin(); it != m_items.end(); ++it) + { + if (pItem == it->get()) + { + m_items.erase(it); + if (m_fastLookup) + { + m_map.erase(m_ignoreURLOptions ? CURL(pItem->GetPath()).GetWithoutOptions() + : pItem->GetPath()); + } + break; + } + } +} + +VECFILEITEMS::iterator CFileItemList::erase(VECFILEITEMS::iterator first, + VECFILEITEMS::iterator last) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + return m_items.erase(first, last); +} + +void CFileItemList::Remove(int iItem) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + + if (iItem >= 0 && iItem < Size()) + { + CFileItemPtr pItem = *(m_items.begin() + iItem); + if (m_fastLookup) + { + m_map.erase(m_ignoreURLOptions ? CURL(pItem->GetPath()).GetWithoutOptions() + : pItem->GetPath()); + } + m_items.erase(m_items.begin() + iItem); + } +} + +void CFileItemList::Append(const CFileItemList& itemlist) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + + for (int i = 0; i < itemlist.Size(); ++i) + Add(itemlist[i]); +} + +void CFileItemList::Assign(const CFileItemList& itemlist, bool append) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + if (!append) + Clear(); + Append(itemlist); + SetPath(itemlist.GetPath()); + SetLabel(itemlist.GetLabel()); + m_sortDetails = itemlist.m_sortDetails; + m_sortDescription = itemlist.m_sortDescription; + m_replaceListing = itemlist.m_replaceListing; + m_content = itemlist.m_content; + m_mapProperties = itemlist.m_mapProperties; + m_cacheToDisc = itemlist.m_cacheToDisc; +} + +bool CFileItemList::Copy(const CFileItemList& items, bool copyItems /* = true */) +{ + // assign all CFileItem parts + *static_cast<CFileItem*>(this) = static_cast<const CFileItem&>(items); + + // assign the rest of the CFileItemList properties + m_replaceListing = items.m_replaceListing; + m_content = items.m_content; + m_mapProperties = items.m_mapProperties; + m_cacheToDisc = items.m_cacheToDisc; + m_sortDetails = items.m_sortDetails; + m_sortDescription = items.m_sortDescription; + m_sortIgnoreFolders = items.m_sortIgnoreFolders; + + if (copyItems) + { + // make a copy of each item + for (int i = 0; i < items.Size(); i++) + { + CFileItemPtr newItem(new CFileItem(*items[i])); + Add(newItem); + } + } + + return true; +} + +CFileItemPtr CFileItemList::Get(int iItem) const +{ + std::unique_lock<CCriticalSection> lock(m_lock); + + if (iItem > -1 && iItem < (int)m_items.size()) + return m_items[iItem]; + + return CFileItemPtr(); +} + +CFileItemPtr CFileItemList::Get(const std::string& strPath) const +{ + std::unique_lock<CCriticalSection> lock(m_lock); + + if (m_fastLookup) + { + MAPFILEITEMS::const_iterator it = + m_map.find(m_ignoreURLOptions ? CURL(strPath).GetWithoutOptions() : strPath); + if (it != m_map.end()) + return it->second; + + return CFileItemPtr(); + } + // slow method... + for (unsigned int i = 0; i < m_items.size(); i++) + { + CFileItemPtr pItem = m_items[i]; + if (pItem->IsPath(m_ignoreURLOptions ? CURL(strPath).GetWithoutOptions() : strPath)) + return pItem; + } + + return CFileItemPtr(); +} + +int CFileItemList::Size() const +{ + std::unique_lock<CCriticalSection> lock(m_lock); + return (int)m_items.size(); +} + +bool CFileItemList::IsEmpty() const +{ + std::unique_lock<CCriticalSection> lock(m_lock); + return m_items.empty(); +} + +void CFileItemList::Reserve(size_t iCount) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + m_items.reserve(iCount); +} + +void CFileItemList::Sort(FILEITEMLISTCOMPARISONFUNC func) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + std::stable_sort(m_items.begin(), m_items.end(), func); +} + +void CFileItemList::FillSortFields(FILEITEMFILLFUNC func) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + std::for_each(m_items.begin(), m_items.end(), func); +} + +void CFileItemList::Sort(SortBy sortBy, + SortOrder sortOrder, + SortAttribute sortAttributes /* = SortAttributeNone */) +{ + if (sortBy == SortByNone || + (m_sortDescription.sortBy == sortBy && m_sortDescription.sortOrder == sortOrder && + m_sortDescription.sortAttributes == sortAttributes)) + return; + + SortDescription sorting; + sorting.sortBy = sortBy; + sorting.sortOrder = sortOrder; + sorting.sortAttributes = sortAttributes; + + Sort(sorting); + m_sortDescription = sorting; +} + +void CFileItemList::Sort(SortDescription sortDescription) +{ + if (sortDescription.sortBy == SortByFile || sortDescription.sortBy == SortBySortTitle || + sortDescription.sortBy == SortByOriginalTitle || sortDescription.sortBy == SortByDateAdded || + sortDescription.sortBy == SortByRating || sortDescription.sortBy == SortByYear || + sortDescription.sortBy == SortByPlaylistOrder || sortDescription.sortBy == SortByLastPlayed || + sortDescription.sortBy == SortByPlaycount) + sortDescription.sortAttributes = + (SortAttribute)((int)sortDescription.sortAttributes | SortAttributeIgnoreFolders); + + if (sortDescription.sortBy == SortByNone || + (m_sortDescription.sortBy == sortDescription.sortBy && + m_sortDescription.sortOrder == sortDescription.sortOrder && + m_sortDescription.sortAttributes == sortDescription.sortAttributes)) + return; + + if (m_sortIgnoreFolders) + sortDescription.sortAttributes = + (SortAttribute)((int)sortDescription.sortAttributes | SortAttributeIgnoreFolders); + + const Fields fields = SortUtils::GetFieldsForSorting(sortDescription.sortBy); + SortItems sortItems((size_t)Size()); + for (int index = 0; index < Size(); index++) + { + sortItems[index] = std::make_shared<SortItem>(); + m_items[index]->ToSortable(*sortItems[index], fields); + (*sortItems[index])[FieldId] = index; + } + + // do the sorting + SortUtils::Sort(sortDescription, sortItems); + + // apply the new order to the existing CFileItems + VECFILEITEMS sortedFileItems; + sortedFileItems.reserve(Size()); + for (SortItems::const_iterator it = sortItems.begin(); it != sortItems.end(); ++it) + { + CFileItemPtr item = m_items[(int)(*it)->at(FieldId).asInteger()]; + // Set the sort label in the CFileItem + item->SetSortLabel((*it)->at(FieldSort).asWideString()); + + sortedFileItems.push_back(item); + } + + // replace the current list with the re-ordered one + m_items = std::move(sortedFileItems); +} + +void CFileItemList::Randomize() +{ + std::unique_lock<CCriticalSection> lock(m_lock); + KODI::UTILS::RandomShuffle(m_items.begin(), m_items.end()); +} + +void CFileItemList::Archive(CArchive& ar) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + if (ar.IsStoring()) + { + CFileItem::Archive(ar); + + int i = 0; + if (!m_items.empty() && m_items[0]->IsParentFolder()) + i = 1; + + ar << (int)(m_items.size() - i); + + ar << m_ignoreURLOptions; + + ar << m_fastLookup; + + ar << (int)m_sortDescription.sortBy; + ar << (int)m_sortDescription.sortOrder; + ar << (int)m_sortDescription.sortAttributes; + ar << m_sortIgnoreFolders; + ar << (int)m_cacheToDisc; + + ar << (int)m_sortDetails.size(); + for (unsigned int j = 0; j < m_sortDetails.size(); ++j) + { + const GUIViewSortDetails& details = m_sortDetails[j]; + ar << (int)details.m_sortDescription.sortBy; + ar << (int)details.m_sortDescription.sortOrder; + ar << (int)details.m_sortDescription.sortAttributes; + ar << details.m_buttonLabel; + ar << details.m_labelMasks.m_strLabelFile; + ar << details.m_labelMasks.m_strLabelFolder; + ar << details.m_labelMasks.m_strLabel2File; + ar << details.m_labelMasks.m_strLabel2Folder; + } + + ar << m_content; + + for (; i < (int)m_items.size(); ++i) + { + CFileItemPtr pItem = m_items[i]; + ar << *pItem; + } + } + else + { + CFileItemPtr pParent; + if (!IsEmpty()) + { + CFileItemPtr pItem = m_items[0]; + if (pItem->IsParentFolder()) + pParent = std::make_shared<CFileItem>(*pItem); + } + + SetIgnoreURLOptions(false); + SetFastLookup(false); + Clear(); + + CFileItem::Archive(ar); + + int iSize = 0; + ar >> iSize; + if (iSize <= 0) + return; + + if (pParent) + { + m_items.reserve(iSize + 1); + m_items.push_back(pParent); + } + else + m_items.reserve(iSize); + + bool ignoreURLOptions = false; + ar >> ignoreURLOptions; + + bool fastLookup = false; + ar >> fastLookup; + + int tempint; + ar >> tempint; + m_sortDescription.sortBy = (SortBy)tempint; + ar >> tempint; + m_sortDescription.sortOrder = (SortOrder)tempint; + ar >> tempint; + m_sortDescription.sortAttributes = (SortAttribute)tempint; + ar >> m_sortIgnoreFolders; + ar >> tempint; + m_cacheToDisc = CACHE_TYPE(tempint); + + unsigned int detailSize = 0; + ar >> detailSize; + for (unsigned int j = 0; j < detailSize; ++j) + { + GUIViewSortDetails details; + ar >> tempint; + details.m_sortDescription.sortBy = (SortBy)tempint; + ar >> tempint; + details.m_sortDescription.sortOrder = (SortOrder)tempint; + ar >> tempint; + details.m_sortDescription.sortAttributes = (SortAttribute)tempint; + ar >> details.m_buttonLabel; + ar >> details.m_labelMasks.m_strLabelFile; + ar >> details.m_labelMasks.m_strLabelFolder; + ar >> details.m_labelMasks.m_strLabel2File; + ar >> details.m_labelMasks.m_strLabel2Folder; + m_sortDetails.push_back(details); + } + + ar >> m_content; + + for (int i = 0; i < iSize; ++i) + { + CFileItemPtr pItem(new CFileItem); + ar >> *pItem; + Add(pItem); + } + + SetIgnoreURLOptions(ignoreURLOptions); + SetFastLookup(fastLookup); + } +} + +void CFileItemList::FillInDefaultIcons() +{ + std::unique_lock<CCriticalSection> lock(m_lock); + for (int i = 0; i < (int)m_items.size(); ++i) + { + CFileItemPtr pItem = m_items[i]; + pItem->FillInDefaultIcon(); + } +} + +int CFileItemList::GetFolderCount() const +{ + std::unique_lock<CCriticalSection> lock(m_lock); + int nFolderCount = 0; + for (int i = 0; i < (int)m_items.size(); i++) + { + CFileItemPtr pItem = m_items[i]; + if (pItem->m_bIsFolder) + nFolderCount++; + } + + return nFolderCount; +} + +int CFileItemList::GetObjectCount() const +{ + std::unique_lock<CCriticalSection> lock(m_lock); + + int numObjects = (int)m_items.size(); + if (numObjects && m_items[0]->IsParentFolder()) + numObjects--; + + return numObjects; +} + +int CFileItemList::GetFileCount() const +{ + std::unique_lock<CCriticalSection> lock(m_lock); + int nFileCount = 0; + for (int i = 0; i < (int)m_items.size(); i++) + { + CFileItemPtr pItem = m_items[i]; + if (!pItem->m_bIsFolder) + nFileCount++; + } + + return nFileCount; +} + +int CFileItemList::GetSelectedCount() const +{ + std::unique_lock<CCriticalSection> lock(m_lock); + int count = 0; + for (int i = 0; i < (int)m_items.size(); i++) + { + CFileItemPtr pItem = m_items[i]; + if (pItem->IsSelected()) + count++; + } + + return count; +} + +void CFileItemList::FilterCueItems() +{ + std::unique_lock<CCriticalSection> lock(m_lock); + // Handle .CUE sheet files... + std::vector<std::string> itemstodelete; + for (int i = 0; i < (int)m_items.size(); i++) + { + CFileItemPtr pItem = m_items[i]; + if (!pItem->m_bIsFolder) + { // see if it's a .CUE sheet + if (pItem->IsCUESheet()) + { + CCueDocumentPtr cuesheet(new CCueDocument); + if (cuesheet->ParseFile(pItem->GetPath())) + { + std::vector<std::string> MediaFileVec; + cuesheet->GetMediaFiles(MediaFileVec); + + // queue the cue sheet and the underlying media file for deletion + for (std::vector<std::string>::iterator itMedia = MediaFileVec.begin(); + itMedia != MediaFileVec.end(); ++itMedia) + { + std::string strMediaFile = *itMedia; + std::string fileFromCue = + strMediaFile; // save the file from the cue we're matching against, + // as we're going to search for others here... + bool bFoundMediaFile = CFile::Exists(strMediaFile); + if (!bFoundMediaFile) + { + // try file in same dir, not matching case... + if (Contains(strMediaFile)) + { + bFoundMediaFile = true; + } + else + { + // try removing the .cue extension... + strMediaFile = pItem->GetPath(); + URIUtils::RemoveExtension(strMediaFile); + CFileItem item(strMediaFile, false); + if (item.IsAudio() && Contains(strMediaFile)) + { + bFoundMediaFile = true; + } + else + { // try replacing the extension with one of our allowed ones. + std::vector<std::string> extensions = StringUtils::Split( + CServiceBroker::GetFileExtensionProvider().GetMusicExtensions(), "|"); + for (std::vector<std::string>::const_iterator i = extensions.begin(); + i != extensions.end(); ++i) + { + strMediaFile = URIUtils::ReplaceExtension(pItem->GetPath(), *i); + CFileItem item(strMediaFile, false); + if (!item.IsCUESheet() && !item.IsPlayList() && Contains(strMediaFile)) + { + bFoundMediaFile = true; + break; + } + } + } + } + } + if (bFoundMediaFile) + { + cuesheet->UpdateMediaFile(fileFromCue, strMediaFile); + // apply CUE for later processing + for (int j = 0; j < (int)m_items.size(); j++) + { + CFileItemPtr pItem = m_items[j]; + if (StringUtils::CompareNoCase(pItem->GetPath(), strMediaFile) == 0) + pItem->SetCueDocument(cuesheet); + } + } + } + } + itemstodelete.push_back(pItem->GetPath()); + } + } + } + // now delete the .CUE files. + for (int i = 0; i < (int)itemstodelete.size(); i++) + { + for (int j = 0; j < (int)m_items.size(); j++) + { + CFileItemPtr pItem = m_items[j]; + if (StringUtils::CompareNoCase(pItem->GetPath(), itemstodelete[i]) == 0) + { // delete this item + m_items.erase(m_items.begin() + j); + break; + } + } + } +} + +// Remove the extensions from the filenames +void CFileItemList::RemoveExtensions() +{ + std::unique_lock<CCriticalSection> lock(m_lock); + for (int i = 0; i < Size(); ++i) + m_items[i]->RemoveExtension(); +} + +void CFileItemList::Stack(bool stackFiles /* = true */) +{ + std::unique_lock<CCriticalSection> lock(m_lock); + + // not allowed here + if (IsVirtualDirectoryRoot() || IsLiveTV() || IsSourcesPath() || IsLibraryFolder()) + return; + + SetProperty("isstacked", true); + + // items needs to be sorted for stuff below to work properly + Sort(SortByLabel, SortOrderAscending); + + StackFolders(); + + if (stackFiles) + StackFiles(); +} + +void CFileItemList::StackFolders() +{ + // Precompile our REs + VECCREGEXP folderRegExps; + CRegExp folderRegExp(true, CRegExp::autoUtf8); + const std::vector<std::string>& strFolderRegExps = + CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_folderStackRegExps; + + std::vector<std::string>::const_iterator strExpression = strFolderRegExps.begin(); + while (strExpression != strFolderRegExps.end()) + { + if (!folderRegExp.RegComp(*strExpression)) + CLog::Log(LOGERROR, "{}: Invalid folder stack RegExp:'{}'", __FUNCTION__, + strExpression->c_str()); + else + folderRegExps.push_back(folderRegExp); + + ++strExpression; + } + + if (!folderRegExp.IsCompiled()) + { + CLog::Log(LOGDEBUG, "{}: No stack expressions available. Skipping folder stacking", + __FUNCTION__); + return; + } + + // stack folders + for (int i = 0; i < Size(); i++) + { + CFileItemPtr item = Get(i); + // combined the folder checks + if (item->m_bIsFolder) + { + // only check known fast sources? + // NOTES: + // 1. rars and zips may be on slow sources? is this supposed to be allowed? + if (!item->IsRemote() || item->IsSmb() || item->IsNfs() || + URIUtils::IsInRAR(item->GetPath()) || URIUtils::IsInZIP(item->GetPath()) || + URIUtils::IsOnLAN(item->GetPath())) + { + // stack cd# folders if contains only a single video file + + bool bMatch(false); + + VECCREGEXP::iterator expr = folderRegExps.begin(); + while (!bMatch && expr != folderRegExps.end()) + { + //CLog::Log(LOGDEBUG,"{}: Running expression {} on {}", __FUNCTION__, expr->GetPattern(), item->GetLabel()); + bMatch = (expr->RegFind(item->GetLabel().c_str()) != -1); + if (bMatch) + { + CFileItemList items; + CDirectory::GetDirectory( + item->GetPath(), items, + CServiceBroker::GetFileExtensionProvider().GetVideoExtensions(), DIR_FLAG_DEFAULTS); + // optimized to only traverse listing once by checking for filecount + // and recording last file item for later use + int nFiles = 0; + int index = -1; + for (int j = 0; j < items.Size(); j++) + { + if (!items[j]->m_bIsFolder) + { + nFiles++; + index = j; + } + + if (nFiles > 1) + break; + } + + if (nFiles == 1) + *item = *items[index]; + } + ++expr; + } + + // check for dvd folders + if (!bMatch) + { + std::string dvdPath = VIDEO_UTILS::GetOpticalMediaPath(*item); + + if (!dvdPath.empty()) + { + // NOTE: should this be done for the CD# folders too? + item->m_bIsFolder = false; + item->SetPath(dvdPath); + item->SetLabel2(""); + item->SetLabelPreformatted(true); + m_sortDescription.sortBy = SortByNone; /* sorting is now broken */ + } + } + } + } + } +} + +void CFileItemList::StackFiles() +{ + // Precompile our REs + VECCREGEXP stackRegExps; + CRegExp tmpRegExp(true, CRegExp::autoUtf8); + const std::vector<std::string>& strStackRegExps = + CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoStackRegExps; + std::vector<std::string>::const_iterator strRegExp = strStackRegExps.begin(); + while (strRegExp != strStackRegExps.end()) + { + if (tmpRegExp.RegComp(*strRegExp)) + { + if (tmpRegExp.GetCaptureTotal() == 4) + stackRegExps.push_back(tmpRegExp); + else + CLog::Log(LOGERROR, "Invalid video stack RE ({}). Must have 4 captures.", *strRegExp); + } + ++strRegExp; + } + + // now stack the files, some of which may be from the previous stack iteration + int i = 0; + while (i < Size()) + { + CFileItemPtr item1 = Get(i); + + // skip folders, nfo files, playlists + if (item1->m_bIsFolder || item1->IsParentFolder() || item1->IsNFO() || item1->IsPlayList()) + { + // increment index + i++; + continue; + } + + int64_t size = 0; + size_t offset = 0; + std::string stackName; + std::string file1; + std::string filePath; + std::vector<int> stack; + VECCREGEXP::iterator expr = stackRegExps.begin(); + + URIUtils::Split(item1->GetPath(), filePath, file1); + if (URIUtils::HasEncodedFilename(CURL(filePath))) + file1 = CURL::Decode(file1); + + int j; + while (expr != stackRegExps.end()) + { + if (expr->RegFind(file1, offset) != -1) + { + std::string Title1 = expr->GetMatch(1), Volume1 = expr->GetMatch(2), + Ignore1 = expr->GetMatch(3), Extension1 = expr->GetMatch(4); + if (offset) + Title1 = file1.substr(0, expr->GetSubStart(2)); + j = i + 1; + while (j < Size()) + { + CFileItemPtr item2 = Get(j); + + // skip folders, nfo files, playlists + if (item2->m_bIsFolder || item2->IsParentFolder() || item2->IsNFO() || + item2->IsPlayList()) + { + // increment index + j++; + continue; + } + + std::string file2, filePath2; + URIUtils::Split(item2->GetPath(), filePath2, file2); + if (URIUtils::HasEncodedFilename(CURL(filePath2))) + file2 = CURL::Decode(file2); + + if (expr->RegFind(file2, offset) != -1) + { + std::string Title2 = expr->GetMatch(1), Volume2 = expr->GetMatch(2), + Ignore2 = expr->GetMatch(3), Extension2 = expr->GetMatch(4); + if (offset) + Title2 = file2.substr(0, expr->GetSubStart(2)); + if (StringUtils::EqualsNoCase(Title1, Title2)) + { + if (!StringUtils::EqualsNoCase(Volume1, Volume2)) + { + if (StringUtils::EqualsNoCase(Ignore1, Ignore2) && + StringUtils::EqualsNoCase(Extension1, Extension2)) + { + if (stack.empty()) + { + stackName = Title1 + Ignore1 + Extension1; + stack.push_back(i); + size += item1->m_dwSize; + } + stack.push_back(j); + size += item2->m_dwSize; + } + else // Sequel + { + offset = 0; + ++expr; + break; + } + } + else if (!StringUtils::EqualsNoCase(Ignore1, + Ignore2)) // False positive, try again with offset + { + offset = expr->GetSubStart(3); + break; + } + else // Extension mismatch + { + offset = 0; + ++expr; + break; + } + } + else // Title mismatch + { + offset = 0; + ++expr; + break; + } + } + else // No match 2, next expression + { + offset = 0; + ++expr; + break; + } + j++; + } + if (j == Size()) + expr = stackRegExps.end(); + } + else // No match 1 + { + offset = 0; + ++expr; + } + if (stack.size() > 1) + { + // have a stack, remove the items and add the stacked item + // dont actually stack a multipart rar set, just remove all items but the first + std::string stackPath; + if (Get(stack[0])->IsRAR()) + stackPath = Get(stack[0])->GetPath(); + else + { + CStackDirectory dir; + stackPath = dir.ConstructStackPath(*this, stack); + } + item1->SetPath(stackPath); + // clean up list + for (unsigned k = 1; k < stack.size(); k++) + Remove(i + 1); + // item->m_bIsFolder = true; // don't treat stacked files as folders + // the label may be in a different char set from the filename (eg over smb + // the label is converted from utf8, but the filename is not) + if (!CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( + CSettings::SETTING_FILELISTS_SHOWEXTENSIONS)) + URIUtils::RemoveExtension(stackName); + + item1->SetLabel(stackName); + item1->m_dwSize = size; + break; + } + } + i++; + } +} + +bool CFileItemList::Load(int windowID) +{ + CFile file; + auto path = GetDiscFileCache(windowID); + try + { + if (file.Open(path)) + { + CArchive ar(&file, CArchive::load); + ar >> *this; + CLog::Log(LOGDEBUG, "Loading items: {}, directory: {} sort method: {}, ascending: {}", Size(), + CURL::GetRedacted(GetPath()), m_sortDescription.sortBy, + m_sortDescription.sortOrder == SortOrderAscending ? "true" : "false"); + ar.Close(); + file.Close(); + return true; + } + } + catch (const std::out_of_range&) + { + CLog::Log(LOGERROR, "Corrupt archive: {}", CURL::GetRedacted(path)); + } + + return false; +} + +bool CFileItemList::Save(int windowID) +{ + int iSize = Size(); + if (iSize <= 0) + return false; + + CLog::Log(LOGDEBUG, "Saving fileitems [{}]", CURL::GetRedacted(GetPath())); + + CFile file; + std::string cachefile = GetDiscFileCache(windowID); + if (file.OpenForWrite(cachefile, true)) // overwrite always + { + // Before caching save simplified cache file name in every item so the cache file can be + // identifed and removed if the item is updated. List path and options (used for file + // name when list cached) can not be accurately derived from item path. + StringUtils::Replace(cachefile, "special://temp/archive_cache/", ""); + StringUtils::Replace(cachefile, ".fi", ""); + for (const auto& item : m_items) + item->SetProperty("cachefilename", cachefile); + + CArchive ar(&file, CArchive::store); + ar << *this; + CLog::Log(LOGDEBUG, " -- items: {}, sort method: {}, ascending: {}", iSize, + m_sortDescription.sortBy, + m_sortDescription.sortOrder == SortOrderAscending ? "true" : "false"); + ar.Close(); + file.Close(); + return true; + } + + return false; +} + +void CFileItemList::RemoveDiscCache(int windowID) const +{ + RemoveDiscCache(GetDiscFileCache(windowID)); +} + +void CFileItemList::RemoveDiscCache(const std::string& cacheFile) const +{ + if (CFile::Exists(cacheFile)) + { + CLog::Log(LOGDEBUG, "Clearing cached fileitems [{}]", CURL::GetRedacted(GetPath())); + CFile::Delete(cacheFile); + } +} + +void CFileItemList::RemoveDiscCacheCRC(const std::string& crc) const +{ + std::string cachefile = StringUtils::Format("special://temp/archive_cache/{}.fi", crc); + RemoveDiscCache(cachefile); +} + +std::string CFileItemList::GetDiscFileCache(int windowID) const +{ + std::string strPath(GetPath()); + URIUtils::RemoveSlashAtEnd(strPath); + + uint32_t crc = Crc32::ComputeFromLowerCase(strPath); + + if (IsCDDA() || IsOnDVD()) + return StringUtils::Format("special://temp/archive_cache/r-{:08x}.fi", crc); + + if (IsMusicDb()) + return StringUtils::Format("special://temp/archive_cache/mdb-{:08x}.fi", crc); + + if (VIDEO::IsVideoDb(*this)) + return StringUtils::Format("special://temp/archive_cache/vdb-{:08x}.fi", crc); + + if (IsSmartPlayList()) + return StringUtils::Format("special://temp/archive_cache/sp-{:08x}.fi", crc); + + if (windowID) + return StringUtils::Format("special://temp/archive_cache/{}-{:08x}.fi", windowID, crc); + + return StringUtils::Format("special://temp/archive_cache/{:08x}.fi", crc); +} + +bool CFileItemList::AlwaysCache() const +{ + // some database folders are always cached + if (IsMusicDb()) + return CMusicDatabaseDirectory::CanCache(GetPath()); + if (VIDEO::IsVideoDb(*this)) + return CVideoDatabaseDirectory::CanCache(GetPath()); + if (IsEPG()) + return true; // always cache + return false; +} + +void CFileItemList::Swap(unsigned int item1, unsigned int item2) +{ + if (item1 != item2 && item1 < m_items.size() && item2 < m_items.size()) + std::swap(m_items[item1], m_items[item2]); +} + +bool CFileItemList::UpdateItem(const CFileItem* item) +{ + if (!item) + return false; + + std::unique_lock<CCriticalSection> lock(m_lock); + for (unsigned int i = 0; i < m_items.size(); i++) + { + CFileItemPtr pItem = m_items[i]; + if (pItem->IsSamePath(item)) + { + pItem->UpdateInfo(*item); + return true; + } + } + return false; +} + +void CFileItemList::AddSortMethod(SortBy sortBy, + int buttonLabel, + const LABEL_MASKS& labelMasks, + SortAttribute sortAttributes /* = SortAttributeNone */) +{ + AddSortMethod(sortBy, sortAttributes, buttonLabel, labelMasks); +} + +void CFileItemList::AddSortMethod(SortBy sortBy, + SortAttribute sortAttributes, + int buttonLabel, + const LABEL_MASKS& labelMasks) +{ + SortDescription sorting; + sorting.sortBy = sortBy; + sorting.sortAttributes = sortAttributes; + + AddSortMethod(sorting, buttonLabel, labelMasks); +} + +void CFileItemList::AddSortMethod(SortDescription sortDescription, + int buttonLabel, + const LABEL_MASKS& labelMasks) +{ + GUIViewSortDetails sort; + sort.m_sortDescription = sortDescription; + sort.m_buttonLabel = buttonLabel; + sort.m_labelMasks = labelMasks; + + m_sortDetails.push_back(sort); +} + +void CFileItemList::SetReplaceListing(bool replace) +{ + m_replaceListing = replace; +} + +void CFileItemList::ClearSortState() +{ + m_sortDescription.sortBy = SortByNone; + m_sortDescription.sortOrder = SortOrderNone; + m_sortDescription.sortAttributes = SortAttributeNone; +} diff --git a/xbmc/FileItemList.h b/xbmc/FileItemList.h new file mode 100644 index 0000000000..5f04f179d2 --- /dev/null +++ b/xbmc/FileItemList.h @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2005-2018 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 + +/*! + \file FileItemList.h + \brief + */ + +#include "FileItem.h" + +/*! + \brief Represents a list of files + \sa CFileItemList, CFileItem + */ +class CFileItemList : public CFileItem +{ +public: + enum CACHE_TYPE + { + CACHE_NEVER = 0, + CACHE_IF_SLOW, + CACHE_ALWAYS + }; + + CFileItemList(); + explicit CFileItemList(const std::string& strPath); + ~CFileItemList() override; + void Archive(CArchive& ar) override; + CFileItemPtr operator[](int iItem); + const CFileItemPtr operator[](int iItem) const; + CFileItemPtr operator[](const std::string& strPath); + const CFileItemPtr operator[](const std::string& strPath) const; + void Clear(); + void ClearItems(); + void Add(CFileItemPtr item); + void Add(CFileItem&& item); + void AddFront(const CFileItemPtr& pItem, int itemPosition); + void Remove(CFileItem* pItem); + void Remove(int iItem); + CFileItemPtr Get(int iItem) const; + const VECFILEITEMS& GetList() const { return m_items; } + CFileItemPtr Get(const std::string& strPath) const; + int Size() const; + bool IsEmpty() const; + void Append(const CFileItemList& itemlist); + void Assign(const CFileItemList& itemlist, bool append = false); + bool Copy(const CFileItemList& item, bool copyItems = true); + void Reserve(size_t iCount); + void Sort(SortBy sortBy, SortOrder sortOrder, SortAttribute sortAttributes = SortAttributeNone); + /* \brief Sorts the items based on the given sorting options + + In contrast to Sort (see above) this does not change the internal + state by storing the sorting method and order used and therefore + will always execute the sorting even if the list of items has + already been sorted with the same options before. + */ + void Sort(SortDescription sortDescription); + void Randomize(); + void FillInDefaultIcons(); + int GetFolderCount() const; + int GetFileCount() const; + int GetSelectedCount() const; + int GetObjectCount() const; + void FilterCueItems(); + void RemoveExtensions(); + void SetIgnoreURLOptions(bool ignoreURLOptions); + void SetFastLookup(bool fastLookup); + bool Contains(const std::string& fileName) const; + bool GetFastLookup() const { return m_fastLookup; } + + /*! \brief stack a CFileItemList + By default we stack all items (files and folders) in a CFileItemList + \param stackFiles whether to stack all items or just collapse folders (defaults to true) + \sa StackFiles,StackFolders + */ + void Stack(bool stackFiles = true); + + SortOrder GetSortOrder() const { return m_sortDescription.sortOrder; } + SortBy GetSortMethod() const { return m_sortDescription.sortBy; } + void SetSortOrder(SortOrder sortOrder) { m_sortDescription.sortOrder = sortOrder; } + void SetSortMethod(SortBy sortBy) { m_sortDescription.sortBy = sortBy; } + + /*! \brief load a CFileItemList out of the cache + + The file list may be cached based on which window we're viewing in, as different + windows will be listing different portions of the same URL (eg viewing music files + versus viewing video files) + + \param windowID id of the window that's loading this list (defaults to 0) + \return true if we loaded from the cache, false otherwise. + \sa Save,RemoveDiscCache + */ + bool Load(int windowID = 0); + + /*! \brief save a CFileItemList to the cache + + The file list may be cached based on which window we're viewing in, as different + windows will be listing different portions of the same URL (eg viewing music files + versus viewing video files) + + \param windowID id of the window that's saving this list (defaults to 0) + \return true if successful, false otherwise. + \sa Load,RemoveDiscCache + */ + bool Save(int windowID = 0); + void SetCacheToDisc(CACHE_TYPE cacheToDisc) { m_cacheToDisc = cacheToDisc; } + bool CacheToDiscAlways() const { return m_cacheToDisc == CACHE_ALWAYS; } + bool CacheToDiscIfSlow() const { return m_cacheToDisc == CACHE_IF_SLOW; } + /*! \brief remove a previously cached CFileItemList from the cache + + The file list may be cached based on which window we're viewing in, as different + windows will be listing different portions of the same URL (eg viewing music files + versus viewing video files) + + \param windowID id of the window whose cache we which to remove (defaults to 0) + \sa Save,Load + */ + void RemoveDiscCache(int windowID = 0) const; + void RemoveDiscCache(const std::string& cachefile) const; + void RemoveDiscCacheCRC(const std::string& crc) const; + bool AlwaysCache() const; + + void Swap(unsigned int item1, unsigned int item2); + + /*! \brief Update an item in the item list + \param item the new item, which we match based on path to an existing item in the list + \return true if the item exists in the list (and was thus updated), false otherwise. + */ + bool UpdateItem(const CFileItem* item); + + void AddSortMethod(SortBy sortBy, + int buttonLabel, + const LABEL_MASKS& labelMasks, + SortAttribute sortAttributes = SortAttributeNone); + void AddSortMethod(SortBy sortBy, + SortAttribute sortAttributes, + int buttonLabel, + const LABEL_MASKS& labelMasks); + void AddSortMethod(SortDescription sortDescription, + int buttonLabel, + const LABEL_MASKS& labelMasks); + bool HasSortDetails() const { return m_sortDetails.size() != 0; } + const std::vector<GUIViewSortDetails>& GetSortDetails() const { return m_sortDetails; } + + /*! \brief Specify whether this list should be sorted with folders separate from files + By default we sort with folders listed (and sorted separately) except for those sort modes + which should be explicitly sorted with folders interleaved with files (eg SORT_METHOD_FILES). + With this set the folder state will be ignored, allowing folders and files to sort interleaved. + \param sort whether to ignore the folder state. + */ + void SetSortIgnoreFolders(bool sort) { m_sortIgnoreFolders = sort; } + bool GetReplaceListing() const { return m_replaceListing; } + void SetReplaceListing(bool replace); + void SetContent(const std::string& content) { m_content = content; } + const std::string& GetContent() const { return m_content; } + + void ClearSortState(); + + VECFILEITEMS::iterator begin() { return m_items.begin(); } + VECFILEITEMS::iterator end() { return m_items.end(); } + VECFILEITEMS::iterator erase(VECFILEITEMS::iterator first, VECFILEITEMS::iterator last); + VECFILEITEMS::const_iterator begin() const { return m_items.begin(); } + VECFILEITEMS::const_iterator end() const { return m_items.end(); } + VECFILEITEMS::const_iterator cbegin() const { return m_items.cbegin(); } + VECFILEITEMS::const_iterator cend() const { return m_items.cend(); } + std::reverse_iterator<VECFILEITEMS::const_iterator> rbegin() const { return m_items.rbegin(); } + std::reverse_iterator<VECFILEITEMS::const_iterator> rend() const { return m_items.rend(); } + +private: + void Sort(FILEITEMLISTCOMPARISONFUNC func); + void FillSortFields(FILEITEMFILLFUNC func); + std::string GetDiscFileCache(int windowID) const; + + /*! + \brief stack files in a CFileItemList + \sa Stack + */ + void StackFiles(); + + /*! + \brief stack folders in a CFileItemList + \sa Stack + */ + void StackFolders(); + + VECFILEITEMS m_items; + MAPFILEITEMS m_map; + bool m_ignoreURLOptions = false; + bool m_fastLookup = false; + SortDescription m_sortDescription; + bool m_sortIgnoreFolders = false; + CACHE_TYPE m_cacheToDisc = CACHE_IF_SLOW; + bool m_replaceListing = false; + std::string m_content; + + std::vector<GUIViewSortDetails> m_sortDetails; + + mutable CCriticalSection m_lock; +}; diff --git a/xbmc/NfoFile.cpp b/xbmc/NfoFile.cpp index 2a11da2c17..f74d0efd20 100644 --- a/xbmc/NfoFile.cpp +++ b/xbmc/NfoFile.cpp @@ -12,6 +12,7 @@ #include "NfoFile.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "addons/AddonManager.h" #include "addons/AddonSystemSettings.h" diff --git a/xbmc/PartyModeManager.cpp b/xbmc/PartyModeManager.cpp index 829a9191f5..dd74bad29e 100644 --- a/xbmc/PartyModeManager.cpp +++ b/xbmc/PartyModeManager.cpp @@ -9,6 +9,7 @@ #include "PartyModeManager.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "PlayListPlayer.h" #include "ServiceBroker.h" diff --git a/xbmc/PlayListPlayer.cpp b/xbmc/PlayListPlayer.cpp index 96cdccb609..feaa7f4fb4 100644 --- a/xbmc/PlayListPlayer.cpp +++ b/xbmc/PlayListPlayer.cpp @@ -9,6 +9,7 @@ #include "PlayListPlayer.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "PartyModeManager.h" #include "ServiceBroker.h" @@ -333,7 +334,7 @@ bool CPlayListPlayer::Play(int iSong, m_iCurrentSong = iSong; CFileItemPtr item = playlist[m_iCurrentSong]; - if (item->IsVideoDb() && !item->HasVideoInfoTag()) + if (IsVideoDb(*item) && !item->HasVideoInfoTag()) *(item->GetVideoInfoTag()) = XFILE::CVideoDatabaseFile::GetVideoTag(CURL(item->GetDynPath())); playlist.SetPlayed(true); diff --git a/xbmc/URL.cpp b/xbmc/URL.cpp index 99b661e36f..073d1104e0 100644 --- a/xbmc/URL.cpp +++ b/xbmc/URL.cpp @@ -7,15 +7,17 @@ */ #include "URL.h" -#include "utils/log.h" -#include "utils/URIUtils.h" -#include "utils/StringUtils.h" + +#include "FileItem.h" +#include "FileItemList.h" +#include "ServiceBroker.h" #include "Util.h" #include "filesystem/File.h" -#include "FileItem.h" #include "filesystem/StackDirectory.h" #include "network/Network.h" -#include "ServiceBroker.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "utils/log.h" #ifndef TARGET_POSIX #include <sys\stat.h> #endif diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp index 2922b66974..7c69b56425 100644 --- a/xbmc/addons/AddonManager.cpp +++ b/xbmc/addons/AddonManager.cpp @@ -10,6 +10,7 @@ #include "CompileInfo.h" #include "FileItem.h" +#include "FileItemList.h" #include "LangInfo.h" #include "ServiceBroker.h" #include "addons/AddonBuilder.h" diff --git a/xbmc/addons/AddonManager.h b/xbmc/addons/AddonManager.h index 10668125c0..fd7ee70f66 100644 --- a/xbmc/addons/AddonManager.h +++ b/xbmc/addons/AddonManager.h @@ -16,6 +16,7 @@ #include <mutex> #include <set> #include <string> +#include <utility> #include <vector> namespace ADDON @@ -37,10 +38,10 @@ using ADDON_INFO_LIST = std::map<std::string, AddonInfoPtr>; class IAddon; using AddonPtr = std::shared_ptr<IAddon>; +using AddonWithUpdate = std::pair<std::shared_ptr<IAddon>, std::shared_ptr<IAddon>>; using VECADDONS = std::vector<AddonPtr>; struct AddonEvent; -struct AddonWithUpdate; struct DependencyInfo; struct RepositoryDirInfo; diff --git a/xbmc/addons/AddonRepos.cpp b/xbmc/addons/AddonRepos.cpp index 5455ca4487..362f051b97 100644 --- a/xbmc/addons/AddonRepos.cpp +++ b/xbmc/addons/AddonRepos.cpp @@ -122,20 +122,16 @@ bool CAddonRepos::LoadAddonsFromDatabase(const std::string& addonId, { if (m_addonMgr.IsCompatible(addon)) { - m_addonsByRepoMap[addon->Origin()].insert({addon->ID(), addon}); + m_addonsByRepoMap[addon->Origin()].emplace(addon->ID(), addon); } } - for (const auto& repo : m_addonsByRepoMap) + for (const auto& [repoId, addonsPerRepo] : m_addonsByRepoMap) { - CLog::LogFC(LOGDEBUG, LOGADDONS, "{} - {} addon(s) loaded", repo.first, repo.second.size()); + CLog::LogFC(LOGDEBUG, LOGADDONS, "{} - {} addon(s) loaded", repoId, addonsPerRepo.size()); - const auto& addonsPerRepo = repo.second; - - for (const auto& addonMapEntry : addonsPerRepo) + for (const auto& [addonId, addonToAdd] : addonsPerRepo) { - const auto& addonToAdd = addonMapEntry.second; - if (IsFromOfficialRepo(addonToAdd, CheckAddonPath::CHOICE_YES)) { AddAddonIfLatest(addonToAdd, m_latestOfficialVersions); @@ -146,7 +142,7 @@ bool CAddonRepos::LoadAddonsFromDatabase(const std::string& addonId, } // add to latestVersionsByRepo - AddAddonIfLatest(repo.first, addonToAdd, m_latestVersionsByRepo); + AddAddonIfLatest(repoId, addonToAdd, m_latestVersionsByRepo); } } @@ -156,8 +152,8 @@ bool CAddonRepos::LoadAddonsFromDatabase(const std::string& addonId, void CAddonRepos::AddAddonIfLatest(const std::shared_ptr<IAddon>& addonToAdd, std::map<std::string, std::shared_ptr<IAddon>>& map) const { - const auto& latestKnown = map.find(addonToAdd->ID()); - if (latestKnown == map.end() || addonToAdd->Version() > latestKnown->second->Version()) + const auto latestKnownIt = map.find(addonToAdd->ID()); + if (latestKnownIt == map.end() || addonToAdd->Version() > latestKnownIt->second->Version()) map[addonToAdd->ID()] = addonToAdd; } @@ -166,21 +162,23 @@ void CAddonRepos::AddAddonIfLatest( const std::shared_ptr<IAddon>& addonToAdd, std::map<std::string, std::map<std::string, std::shared_ptr<IAddon>>>& map) const { - const auto& latestVersionByRepo = map.find(repoId); + bool doInsert{true}; - if (latestVersionByRepo == map.end()) // repo not found - { - map[repoId].insert({addonToAdd->ID(), addonToAdd}); - } - else + const auto latestVersionByRepoIt = map.find(repoId); + if (latestVersionByRepoIt != map.end()) // we already have this repository in the outer map { - const auto& latestVersionEntryByRepo = latestVersionByRepo->second; - const auto& latestKnown = latestVersionEntryByRepo.find(addonToAdd->ID()); + const auto& latestVersionEntryByRepo = latestVersionByRepoIt->second; + const auto latestKnownIt = latestVersionEntryByRepo.find(addonToAdd->ID()); - if (latestKnown == latestVersionEntryByRepo.end() || - addonToAdd->Version() > latestKnown->second->Version()) - map[repoId][addonToAdd->ID()] = addonToAdd; + if (latestKnownIt != latestVersionEntryByRepo.end() && + addonToAdd->Version() <= latestKnownIt->second->Version()) + { + doInsert = false; + } } + + if (doInsert) + map[repoId][addonToAdd->ID()] = addonToAdd; } void CAddonRepos::BuildUpdateOrOutdatedList(const std::vector<std::shared_ptr<IAddon>>& installed, @@ -212,7 +210,7 @@ void CAddonRepos::BuildAddonsWithUpdateList( { if (DoAddonUpdateCheck(addon, update)) { - addonsWithUpdate.insert({addon->ID(), {addon, update}}); + addonsWithUpdate.try_emplace(addon->ID(), addon, update); } } } @@ -253,10 +251,10 @@ bool CAddonRepos::DoAddonUpdateCheck(const std::shared_ptr<IAddon>& addon, else { // ...we check for updates in the origin repo only - const auto& repoEntry = m_latestVersionsByRepo.find(addon->Origin()); - if (repoEntry != m_latestVersionsByRepo.end()) + const auto repoEntryIt = m_latestVersionsByRepo.find(addon->Origin()); + if (repoEntryIt != m_latestVersionsByRepo.end()) { - if (!FindAddonAndCheckForUpdate(addon, repoEntry->second, update)) + if (!FindAddonAndCheckForUpdate(addon, repoEntryIt->second, update)) { return false; } @@ -280,14 +278,14 @@ bool CAddonRepos::FindAddonAndCheckForUpdate( const std::map<std::string, std::shared_ptr<IAddon>>& map, std::shared_ptr<IAddon>& update) const { - const auto& remote = map.find(addonToCheck->ID()); - if (remote != map.end()) // is addon in the desired map? + const auto remoteIt = map.find(addonToCheck->ID()); + if (remoteIt != map.end()) // is addon in the desired map? { - if ((remote->second->Version() > addonToCheck->Version()) || + if ((remoteIt->second->Version() > addonToCheck->Version()) || m_addonMgr.IsAddonDisabledWithReason(addonToCheck->ID(), AddonDisabledReason::INCOMPATIBLE)) { // return addon update - update = remote->second; + update = remoteIt->second; return true; // update found } } @@ -300,10 +298,10 @@ bool CAddonRepos::GetLatestVersionByMap(const std::string& addonId, const std::map<std::string, std::shared_ptr<IAddon>>& map, std::shared_ptr<IAddon>& addon) const { - const auto& remote = map.find(addonId); - if (remote != map.end()) // is addon in the desired map? + const auto remoteIt = map.find(addonId); + if (remoteIt != map.end()) // is addon in the desired map? { - addon = remote->second; + addon = remoteIt->second; return true; } @@ -356,14 +354,15 @@ void CAddonRepos::GetLatestAddonVersions(std::vector<std::shared_ptr<IAddon>>& a // then we insert private addon versions if they don't exist in the official map // or installation from ANY_REPOSITORY is allowed and the private version is higher - for (const auto& privateVersion : m_latestPrivateVersions) + for (const auto& [privateVersionId, privateVersion] : m_latestPrivateVersions) { - const auto& officialVersion = m_latestOfficialVersions.find(privateVersion.first); - if (officialVersion == m_latestOfficialVersions.end() || + const auto officialVersionIt = m_latestOfficialVersions.find(privateVersionId); + + if (officialVersionIt == m_latestOfficialVersions.end() || (updateMode == AddonRepoUpdateMode::ANY_REPOSITORY && - privateVersion.second->Version() > officialVersion->second->Version())) + privateVersion->Version() > officialVersionIt->second->Version())) { - addonList.emplace_back(privateVersion.second); + addonList.emplace_back(privateVersion); } } } @@ -390,18 +389,18 @@ void CAddonRepos::GetLatestAddonVersionsFromAllRepos( // so we need to filter them out if (std::none_of(officialRepoInfos.begin(), officialRepoInfos.end(), - [&](const ADDON::RepoInfo& officialRepo) { - return repo.first == officialRepo.m_repoId; - })) + [&repo](const ADDON::RepoInfo& officialRepo) + { return repo.first == officialRepo.m_repoId; })) { - for (const auto& latestAddon : repo.second) + for (const auto& [latestAddonId, latestAddon] : repo.second) { - const auto& officialVersion = m_latestOfficialVersions.find(latestAddon.first); - if (officialVersion == m_latestOfficialVersions.end() || + const auto officialVersionIt = m_latestOfficialVersions.find(latestAddonId); + + if (officialVersionIt == m_latestOfficialVersions.end() || (updateMode == AddonRepoUpdateMode::ANY_REPOSITORY && - latestAddon.second->Version() > officialVersion->second->Version())) + latestAddon->Version() > officialVersionIt->second->Version())) { - addonList.emplace_back(latestAddon.second); + addonList.emplace_back(latestAddon); } } } @@ -469,10 +468,10 @@ bool CAddonRepos::FindDependencyByParentRepo(const std::string& dependsId, const std::string& parentRepoId, std::shared_ptr<IAddon>& dependencyToInstall) const { - const auto& repoEntry = m_latestVersionsByRepo.find(parentRepoId); - if (repoEntry != m_latestVersionsByRepo.end()) + const auto repoEntryIt = m_latestVersionsByRepo.find(parentRepoId); + if (repoEntryIt != m_latestVersionsByRepo.end()) { - if (GetLatestVersionByMap(dependsId, repoEntry->second, dependencyToInstall)) + if (GetLatestVersionByMap(dependsId, repoEntryIt->second, dependencyToInstall)) return true; } diff --git a/xbmc/addons/AddonRepos.h b/xbmc/addons/AddonRepos.h index bb9be3473c..4284674f01 100644 --- a/xbmc/addons/AddonRepos.h +++ b/xbmc/addons/AddonRepos.h @@ -13,6 +13,7 @@ #include <map> #include <memory> #include <string> +#include <utility> #include <vector> namespace ADDON @@ -30,14 +31,7 @@ enum class CheckAddonPath CHOICE_NO = false, }; -/** - * Struct - CAddonWithUpdate - */ -struct AddonWithUpdate -{ - std::shared_ptr<IAddon> m_installed; - std::shared_ptr<IAddon> m_update; -}; +using AddonWithUpdate = std::pair<std::shared_ptr<IAddon>, std::shared_ptr<IAddon>>; /** * Class - CAddonRepos diff --git a/xbmc/addons/FilesystemInstaller.cpp b/xbmc/addons/FilesystemInstaller.cpp index 0f7b32de64..f6dd80131a 100644 --- a/xbmc/addons/FilesystemInstaller.cpp +++ b/xbmc/addons/FilesystemInstaller.cpp @@ -8,6 +8,7 @@ #include "FilesystemInstaller.h" #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/Directory.h" #include "filesystem/File.h" #include "filesystem/SpecialProtocol.h" diff --git a/xbmc/addons/Scraper.cpp b/xbmc/addons/Scraper.cpp index 66cedcb969..b759dc84e7 100644 --- a/xbmc/addons/Scraper.cpp +++ b/xbmc/addons/Scraper.cpp @@ -9,6 +9,7 @@ #include "Scraper.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "Util.h" diff --git a/xbmc/addons/Skin.cpp b/xbmc/addons/Skin.cpp index a6192d902b..746800776c 100644 --- a/xbmc/addons/Skin.cpp +++ b/xbmc/addons/Skin.cpp @@ -9,6 +9,7 @@ #include "Skin.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "Util.h" #include "addons/addoninfo/AddonType.h" diff --git a/xbmc/addons/VFSEntry.h b/xbmc/addons/VFSEntry.h index c11fca05da..414f9593af 100644 --- a/xbmc/addons/VFSEntry.h +++ b/xbmc/addons/VFSEntry.h @@ -8,6 +8,7 @@ #pragma once #include "FileItem.h" +#include "FileItemList.h" #include "addons/binary-addons/AddonDll.h" #include "addons/binary-addons/AddonInstanceHandler.h" #include "addons/kodi-dev-kit/include/kodi/addon-instance/VFS.h" diff --git a/xbmc/addons/addoninfo/AddonInfo.cpp b/xbmc/addons/addoninfo/AddonInfo.cpp index f891e73bc9..0f2f7fba5f 100644 --- a/xbmc/addons/addoninfo/AddonInfo.cpp +++ b/xbmc/addons/addoninfo/AddonInfo.cpp @@ -9,6 +9,7 @@ #include "AddonInfo.h" #include "FileItem.h" +#include "FileItemList.h" #include "LangInfo.h" #include "ServiceBroker.h" #include "addons/AddonManager.h" diff --git a/xbmc/addons/gui/GUIDialogAddonInfo.cpp b/xbmc/addons/gui/GUIDialogAddonInfo.cpp index 671e55dcf4..172af8b216 100644 --- a/xbmc/addons/gui/GUIDialogAddonInfo.cpp +++ b/xbmc/addons/gui/GUIDialogAddonInfo.cpp @@ -9,6 +9,7 @@ #include "GUIDialogAddonInfo.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "ServiceBroker.h" #include "Util.h" diff --git a/xbmc/addons/gui/GUIDialogAddonSettings.cpp b/xbmc/addons/gui/GUIDialogAddonSettings.cpp index 4830283e4d..60cbaa2a2e 100644 --- a/xbmc/addons/gui/GUIDialogAddonSettings.cpp +++ b/xbmc/addons/gui/GUIDialogAddonSettings.cpp @@ -9,6 +9,7 @@ #include "GUIDialogAddonSettings.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" diff --git a/xbmc/addons/gui/GUIViewStateAddonBrowser.cpp b/xbmc/addons/gui/GUIViewStateAddonBrowser.cpp index 5504f33ecd..7ecb3cbcf8 100644 --- a/xbmc/addons/gui/GUIViewStateAddonBrowser.cpp +++ b/xbmc/addons/gui/GUIViewStateAddonBrowser.cpp @@ -9,6 +9,7 @@ #include "GUIViewStateAddonBrowser.h" #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/File.h" #include "guilib/WindowIDs.h" #include "utils/StringUtils.h" diff --git a/xbmc/addons/gui/GUIWindowAddonBrowser.cpp b/xbmc/addons/gui/GUIWindowAddonBrowser.cpp index f130bacad1..880e784835 100644 --- a/xbmc/addons/gui/GUIWindowAddonBrowser.cpp +++ b/xbmc/addons/gui/GUIWindowAddonBrowser.cpp @@ -10,6 +10,7 @@ #include "ContextMenuManager.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIDialogAddonInfo.h" #include "GUIUserMessages.h" #include "LangInfo.h" diff --git a/xbmc/addons/interfaces/Filesystem.cpp b/xbmc/addons/interfaces/Filesystem.cpp index c063b48fd6..9f22b67ecc 100644 --- a/xbmc/addons/interfaces/Filesystem.cpp +++ b/xbmc/addons/interfaces/Filesystem.cpp @@ -9,6 +9,7 @@ #include "Filesystem.h" #include "FileItem.h" +#include "FileItemList.h" #include "Util.h" #include "addons/binary-addons/AddonDll.h" #include "filesystem/CurlFile.h" diff --git a/xbmc/addons/interfaces/gui/Window.cpp b/xbmc/addons/interfaces/gui/Window.cpp index b817d443a3..831b89fdbd 100644 --- a/xbmc/addons/interfaces/gui/Window.cpp +++ b/xbmc/addons/interfaces/gui/Window.cpp @@ -9,6 +9,7 @@ #include "addons/kodi-dev-kit/include/kodi/gui/Window.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUITranslator.h" #include "General.h" #include "ServiceBroker.h" diff --git a/xbmc/addons/settings/AddonSettings.cpp b/xbmc/addons/settings/AddonSettings.cpp index 2fc9f26fae..b3bd9bb124 100644 --- a/xbmc/addons/settings/AddonSettings.cpp +++ b/xbmc/addons/settings/AddonSettings.cpp @@ -9,6 +9,7 @@ #include "AddonSettings.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "LangInfo.h" #include "ServiceBroker.h" diff --git a/xbmc/application/AppParamParser.cpp b/xbmc/application/AppParamParser.cpp index ca9cd2acef..20b54e7869 100644 --- a/xbmc/application/AppParamParser.cpp +++ b/xbmc/application/AppParamParser.cpp @@ -10,6 +10,7 @@ #include "CompileInfo.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "application/AppParams.h" #include "utils/StringUtils.h" diff --git a/xbmc/application/AppParams.cpp b/xbmc/application/AppParams.cpp index 97c09e3934..8b174467b4 100644 --- a/xbmc/application/AppParams.cpp +++ b/xbmc/application/AppParams.cpp @@ -8,12 +8,14 @@ #include "AppParams.h" -#include "FileItem.h" +#include "FileItemList.h" CAppParams::CAppParams() : m_playlist(std::make_unique<CFileItemList>()) { } +CAppParams::~CAppParams() = default; + void CAppParams::SetRawArgs(std::vector<std::string> args) { m_rawArgs = std::move(args); diff --git a/xbmc/application/AppParams.h b/xbmc/application/AppParams.h index 6999249719..12d7aba2b9 100644 --- a/xbmc/application/AppParams.h +++ b/xbmc/application/AppParams.h @@ -21,7 +21,7 @@ class CAppParams { public: CAppParams(); - virtual ~CAppParams() = default; + virtual ~CAppParams(); int GetLogLevel() const { return m_logLevel; } void SetLogLevel(int logLevel) { m_logLevel = logLevel; } diff --git a/xbmc/application/Application.cpp b/xbmc/application/Application.cpp index 4dcb893702..6541a22759 100644 --- a/xbmc/application/Application.cpp +++ b/xbmc/application/Application.cpp @@ -2307,7 +2307,7 @@ bool CApplication::PlayFile(CFileItem item, const std::string& player, bool bRes CUtil::ClearSubtitles(); } - if (item.IsDiscStub()) + if (IsDiscStub(item)) { return CServiceBroker::GetMediaManager().playStubFile(item); } @@ -2356,7 +2356,7 @@ bool CApplication::PlayFile(CFileItem item, const std::string& player, bool bRes std::string path = item.GetPath(); std::string videoInfoTagPath(item.GetVideoInfoTag()->m_strFileNameAndPath); - if (videoInfoTagPath.find("removable://") == 0 || item.IsVideoDb()) + if (videoInfoTagPath.find("removable://") == 0 || IsVideoDb(item)) path = videoInfoTagPath; // Note that we need to load the tag from database also if the item already has a tag, @@ -2426,7 +2426,7 @@ bool CApplication::PlayFile(CFileItem item, const std::string& player, bool bRes // a disc image might be Blu-Ray disc if (!(options.startpercent > 0.0 || options.starttime > 0.0) && - (item.IsBDFile() || item.IsDiscImage())) + (IsBDFile(item) || item.IsDiscImage())) { // No video selection when using external or remote players (they handle it if supported) const bool isSimpleMenuAllowed = [&]() diff --git a/xbmc/application/ApplicationPlayer.cpp b/xbmc/application/ApplicationPlayer.cpp index b517c78fd0..d088f46b6a 100644 --- a/xbmc/application/ApplicationPlayer.cpp +++ b/xbmc/application/ApplicationPlayer.cpp @@ -17,9 +17,11 @@ #include "guilib/GUIWindowManager.h" #include "settings/AdvancedSettings.h" #include "settings/SettingsComponent.h" +#include "video/VideoFileItemClassify.h" #include <mutex> +using namespace KODI; using namespace std::chrono_literals; std::shared_ptr<const IPlayer> CApplicationPlayer::GetInternal() const @@ -99,7 +101,7 @@ bool CApplicationPlayer::OpenFile(const CFileItem& item, const CPlayerOptions& o { bool needToClose = false; - if (item.IsDiscImage() || item.IsDVDFile()) + if (item.IsDiscImage() || VIDEO::IsDVDFile(item)) needToClose = true; if (player->m_name != newPlayer) diff --git a/xbmc/application/ApplicationPlayerCallback.cpp b/xbmc/application/ApplicationPlayerCallback.cpp index 2ff6353952..637f67ddcc 100644 --- a/xbmc/application/ApplicationPlayerCallback.cpp +++ b/xbmc/application/ApplicationPlayerCallback.cpp @@ -57,7 +57,7 @@ void CApplicationPlayerCallback::OnPlayBackStarted(const CFileItem& file) std::shared_ptr<CFileItem> itemCurrentFile; // check if VideoPlayer should set file item stream details from its current streams - const bool isBlu_dvd_image_or_stream = (URIUtils::IsBluray(file.GetPath()) || file.IsDVDFile() || + const bool isBlu_dvd_image_or_stream = (URIUtils::IsBluray(file.GetPath()) || IsDVDFile(file) || file.IsDiscImage() || file.IsInternetStream()); const bool hasNoStreamDetails = diff --git a/xbmc/application/ApplicationSkinHandling.cpp b/xbmc/application/ApplicationSkinHandling.cpp index bf73f14363..5f916060ac 100644 --- a/xbmc/application/ApplicationSkinHandling.cpp +++ b/xbmc/application/ApplicationSkinHandling.cpp @@ -9,6 +9,7 @@ #include "ApplicationSkinHandling.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "GUILargeTextureManager.h" #include "GUIUserMessages.h" diff --git a/xbmc/application/ApplicationStackHelper.cpp b/xbmc/application/ApplicationStackHelper.cpp index 27b7808a2a..515c52b5aa 100644 --- a/xbmc/application/ApplicationStackHelper.cpp +++ b/xbmc/application/ApplicationStackHelper.cpp @@ -9,6 +9,7 @@ #include "ApplicationStackHelper.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "Util.h" #include "cores/VideoPlayer/DVDFileInfo.h" diff --git a/xbmc/cdrip/CDDARipper.cpp b/xbmc/cdrip/CDDARipper.cpp index 41dcc8d5d6..b174c8bbd3 100644 --- a/xbmc/cdrip/CDDARipper.cpp +++ b/xbmc/cdrip/CDDARipper.cpp @@ -10,6 +10,7 @@ #include "CDDARipJob.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "Util.h" #include "addons/AddonManager.h" diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp index 02c8eb1b83..e897cbd3ea 100644 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp @@ -148,21 +148,21 @@ bool CActiveAEResampleFFMPEG::Init(SampleConfig dstConfig, SampleConfig srcConfi AVChannel outChan = av_channel_layout_channel_from_index(&dstChLayout, out); switch (outChan) { - case AV_CH_FRONT_LEFT: - case AV_CH_BACK_LEFT: - case AV_CH_SIDE_LEFT: + case AV_CHAN_FRONT_LEFT: + case AV_CHAN_BACK_LEFT: + case AV_CHAN_SIDE_LEFT: m_rematrix[out][0] = 1.0; break; - case AV_CH_FRONT_RIGHT: - case AV_CH_BACK_RIGHT: - case AV_CH_SIDE_RIGHT: + case AV_CHAN_FRONT_RIGHT: + case AV_CHAN_BACK_RIGHT: + case AV_CHAN_SIDE_RIGHT: m_rematrix[out][1] = 1.0; break; - case AV_CH_FRONT_CENTER: + case AV_CHAN_FRONT_CENTER: m_rematrix[out][0] = 0.5; m_rematrix[out][1] = 0.5; break; - case AV_CH_LOW_FREQUENCY: + case AV_CHAN_LOW_FREQUENCY: m_rematrix[out][0] = 0.5; m_rematrix[out][1] = 0.5; break; diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp index 4b450ec5cb..ca02e2bafa 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp @@ -218,10 +218,10 @@ bool CAESinkDirectSound::Initialize(AEAudioFormat &format, std::string &device) m_AvgBytesPerSec = wfxex.Format.nAvgBytesPerSec; - unsigned int uiFrameCount = (int)(format.m_sampleRate * 0.015); //default to 15ms chunks + const unsigned int uiFrameCount = static_cast<int>(format.m_sampleRate * 0.050); // 50ms chunks m_dwFrameSize = wfxex.Format.nBlockAlign; m_dwChunkSize = m_dwFrameSize * uiFrameCount; - m_dwBufferLen = m_dwChunkSize * 12; //180ms total buffer + m_dwBufferLen = m_dwChunkSize * 8; // 400ms total buffer // fill in the secondary sound buffer descriptor DSBUFFERDESC dsbdesc = {}; diff --git a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp index a2084261b1..b86fa65414 100644 --- a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp +++ b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp @@ -44,6 +44,7 @@ #endif #include "CompileInfo.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "Util.h" diff --git a/xbmc/cores/RetroPlayer/savestates/SavestateDatabase.cpp b/xbmc/cores/RetroPlayer/savestates/SavestateDatabase.cpp index 7864a15261..a6deeddb94 100644 --- a/xbmc/cores/RetroPlayer/savestates/SavestateDatabase.cpp +++ b/xbmc/cores/RetroPlayer/savestates/SavestateDatabase.cpp @@ -9,6 +9,7 @@ #include "SavestateDatabase.h" #include "FileItem.h" +#include "FileItemList.h" #include "SavestateFlatBuffer.h" #include "URL.h" #include "XBDateTime.h" diff --git a/xbmc/cores/VideoPlayer/DVDFileInfo.cpp b/xbmc/cores/VideoPlayer/DVDFileInfo.cpp index bd89cb4629..65dfc539de 100644 --- a/xbmc/cores/VideoPlayer/DVDFileInfo.cpp +++ b/xbmc/cores/VideoPlayer/DVDFileInfo.cpp @@ -11,6 +11,7 @@ #include "DVDInputStreams/DVDInputStream.h" #include "DVDStreamInfo.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "filesystem/StackDirectory.h" #include "guilib/Texture.h" @@ -20,6 +21,7 @@ #include "utils/MemUtils.h" #include "utils/URIUtils.h" #include "utils/log.h" +#include "video/VideoFileItemClassify.h" #include "video/VideoInfoTag.h" #ifdef HAVE_LIBBLURAY #include "DVDInputStreams/DVDInputStreamBluray.h" @@ -49,6 +51,8 @@ extern "C" { #include <libswscale/swscale.h> } +using namespace KODI; + bool CDVDFileInfo::GetFileDuration(const std::string &path, int& duration) { std::unique_ptr<CDVDDemux> demux; @@ -258,12 +262,12 @@ bool CDVDFileInfo::CanExtract(const CFileItem& fileItem) URIUtils::IsPVRRecording(fileItem.GetDynPath()) || // plugin path not fully resolved URIUtils::IsPlugin(fileItem.GetDynPath()) || URIUtils::IsUPnP(fileItem.GetPath()) || - fileItem.IsInternetStream() || fileItem.IsDiscStub() || fileItem.IsPlayList()) + fileItem.IsInternetStream() || VIDEO::IsDiscStub(fileItem) || fileItem.IsPlayList()) return false; // mostly can't extract from discs and files from discs. - if (URIUtils::IsBluray(fileItem.GetPath()) || fileItem.IsBDFile() || fileItem.IsDVD() || - fileItem.IsDiscImage() || fileItem.IsDVDFile(false, true)) + if (URIUtils::IsBluray(fileItem.GetPath()) || VIDEO::IsBDFile(fileItem) || fileItem.IsDVD() || + fileItem.IsDiscImage() || VIDEO::IsDVDFile(fileItem, false, true)) return false; // For HTTP/FTP we only allow extraction when on a LAN diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp index e25e35dcaf..2b65938437 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp @@ -32,9 +32,12 @@ #include "storage/MediaManager.h" #include "utils/FileUtils.h" #include "utils/URIUtils.h" +#include "video/VideoFileItemClassify.h" #include <memory> +using namespace KODI; + std::shared_ptr<CDVDInputStream> CDVDFactoryInputStream::CreateInputStream(IVideoPlayer* pPlayer, const CFileItem &fileitem, bool scanforextaudio) { using namespace ADDON; @@ -101,7 +104,7 @@ std::shared_ptr<CDVDInputStream> CDVDFactoryInputStream::CreateInputStream(IVide } #endif - if (fileitem.IsDVDFile(false, true)) + if (VIDEO::IsDVDFile(fileitem, false, true)) return std::make_shared<CDVDInputStreamNavigator>(pPlayer, fileitem); else if (URIUtils::IsPVRChannel(file)) return std::make_shared<CInputStreamPVRChannel>(pPlayer, fileitem); diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp index a87888c7be..8936399b94 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp @@ -27,6 +27,7 @@ #include "utils/URIUtils.h" #include "utils/XTimeUtils.h" #include "utils/log.h" +#include "video/VideoFileItemClassify.h" #include <functional> #include <limits> @@ -37,6 +38,7 @@ #define LIBBLURAY_BYTESEEK 0 +using namespace KODI; using namespace XFILE; using namespace std::chrono_literals; @@ -152,7 +154,7 @@ bool CDVDInputStreamBluray::Open() // Check whether disc is AACS protected CURL url3(root); CFileItem base(url3, false); - openDisc = base.IsProtectedBlurayDisc(); + openDisc = VIDEO::IsProtectedBlurayDisc(base); // check for a menu call for an image file if (StringUtils::EqualsNoCase(filename, "menu")) @@ -166,7 +168,7 @@ bool CDVDInputStreamBluray::Open() // Check whether disc is AACS protected if (!openDisc) - openDisc = item.IsProtectedBlurayDisc(); + openDisc = VIDEO::IsProtectedBlurayDisc(item); if (item.IsDiscImage()) { @@ -184,7 +186,7 @@ bool CDVDInputStreamBluray::Open() openStream = true; } - else if (m_item.IsProtectedBlurayDisc()) + else if (VIDEO::IsProtectedBlurayDisc(m_item)) { openDisc = true; } diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFile.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFile.cpp index 4214673f08..9ebd8d2c53 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFile.cpp +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFile.cpp @@ -12,7 +12,9 @@ #include "filesystem/IFile.h" #include "utils/URIUtils.h" #include "utils/log.h" +#include "video/VideoFileItemClassify.h" +using namespace KODI; using namespace XFILE; CDVDInputStreamFile::CDVDInputStreamFile(const CFileItem& fileitem, unsigned int flags) @@ -44,7 +46,7 @@ bool CDVDInputStreamFile::Open() unsigned int flags = m_flags; // If this file is audio and/or video (= not a subtitle) flag to caller - if (!m_item.IsSubtitle()) + if (!VIDEO::IsSubtitle(m_item)) flags |= READ_AUDIO_VIDEO; std::string content = m_item.GetMimeType(); diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamStack.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamStack.cpp index 1f018617ac..3788295b01 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamStack.cpp +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamStack.cpp @@ -9,6 +9,7 @@ #include "DVDInputStreamStack.h" #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/File.h" #include "filesystem/StackDirectory.h" #include "utils/log.h" diff --git a/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitlesLibass.cpp b/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitlesLibass.cpp index 7ac7ec7e71..a8a5e0e35f 100644 --- a/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitlesLibass.cpp +++ b/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitlesLibass.cpp @@ -9,6 +9,7 @@ #include "DVDSubtitlesLibass.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "cores/VideoPlayer/Interface/TimingConstants.h" #include "filesystem/Directory.h" diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGL.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGL.cpp index 3caa28e4bf..8559d22eae 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGL.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGL.cpp @@ -293,6 +293,11 @@ void COverlayGlyphGL::Render(SRenderState& state) GLint posLoc = renderSystem->ShaderGetPos(); GLint colLoc = renderSystem->ShaderGetCol(); GLint tex0Loc = renderSystem->ShaderGetCoord0(); + GLint matrixUniformLoc = renderSystem->ShaderGetMatrix(); + + CMatrixGL matrix = glMatrixProject.Get(); + matrix.MultMatrixf(glMatrixModview.Get()); + glUniformMatrix4fv(matrixUniformLoc, 1, GL_FALSE, matrix); std::vector<VERTEX> vecVertices(6 * m_vertex.size() / 4); VERTEX* vertices = vecVertices.data(); diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGLES.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGLES.cpp index cf3b31324a..237afacc42 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGLES.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGLES.cpp @@ -352,6 +352,11 @@ void COverlayGlyphGLES::Render(SRenderState& state) GLint posLoc = renderSystem->GUIShaderGetPos(); GLint colLoc = renderSystem->GUIShaderGetCol(); GLint tex0Loc = renderSystem->GUIShaderGetCoord0(); + GLint matrixUniformLoc = renderSystem->GUIShaderGetMatrix(); + + CMatrixGL matrix = glMatrixProject.Get(); + matrix.MultMatrixf(glMatrixModview.Get()); + glUniformMatrix4fv(matrixUniformLoc, 1, GL_FALSE, matrix); // stack object until VBOs will be used std::vector<VERTEX> vecVertices(6 * m_vertex.size() / 4); diff --git a/xbmc/cores/paplayer/AudioDecoder.cpp b/xbmc/cores/paplayer/AudioDecoder.cpp index 03dc907c0b..a960776287 100644 --- a/xbmc/cores/paplayer/AudioDecoder.cpp +++ b/xbmc/cores/paplayer/AudioDecoder.cpp @@ -75,7 +75,7 @@ bool CAudioDecoder::Create(const CFileItem &file, int64_t seekOffset) filecache = settings->GetInt(CSettings::SETTING_CACHE_HARDDISK); else if ( file.IsOnDVD() ) filecache = settings->GetInt(CSettings::SETTING_CACHEAUDIO_DVDROM); - else if ( file.IsOnLAN() ) + else if (file.IsOnLAN()) filecache = settings->GetInt(CSettings::SETTING_CACHEAUDIO_LAN); // create our codec diff --git a/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp b/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp index 4d4f390b5b..d8441dd0c6 100644 --- a/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp +++ b/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp @@ -128,11 +128,11 @@ void CPlayerSelectionRule::GetPlayers(const CFileItem& item, std::vector<std::st if (m_tRemote >= 0 && (m_tRemote > 0) != item.IsRemote()) return; - if (m_tBD >= 0 && (m_tBD > 0) != (item.IsBDFile() && item.IsOnDVD())) + if (m_tBD >= 0 && (m_tBD > 0) != (VIDEO::IsBDFile(item) && item.IsOnDVD())) return; if (m_tDVD >= 0 && (m_tDVD > 0) != item.IsDVD()) return; - if (m_tDVDFile >= 0 && (m_tDVDFile > 0) != item.IsDVDFile()) + if (m_tDVDFile >= 0 && (m_tDVDFile > 0) != VIDEO::IsDVDFile(item)) return; if (m_tDiscImage >= 0 && (m_tDiscImage > 0) != item.IsDiscImage()) return; diff --git a/xbmc/dialogs/GUIDialogColorPicker.cpp b/xbmc/dialogs/GUIDialogColorPicker.cpp index b4bc59c355..58814de392 100644 --- a/xbmc/dialogs/GUIDialogColorPicker.cpp +++ b/xbmc/dialogs/GUIDialogColorPicker.cpp @@ -9,6 +9,7 @@ #include "GUIDialogColorPicker.h" #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/SpecialProtocol.h" #include "guilib/GUIColorManager.h" #include "guilib/GUIMessage.h" diff --git a/xbmc/dialogs/GUIDialogFileBrowser.cpp b/xbmc/dialogs/GUIDialogFileBrowser.cpp index 9181313747..8fecfb62b6 100644 --- a/xbmc/dialogs/GUIDialogFileBrowser.cpp +++ b/xbmc/dialogs/GUIDialogFileBrowser.cpp @@ -10,6 +10,7 @@ #include "AutoSwitch.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIDialogContextMenu.h" #include "GUIDialogMediaSource.h" #include "GUIDialogYesNo.h" diff --git a/xbmc/dialogs/GUIDialogMediaFilter.cpp b/xbmc/dialogs/GUIDialogMediaFilter.cpp index 14340c85bb..55b1013967 100644 --- a/xbmc/dialogs/GUIDialogMediaFilter.cpp +++ b/xbmc/dialogs/GUIDialogMediaFilter.cpp @@ -10,6 +10,7 @@ #include "DbUrl.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" #include "XBDateTime.h" diff --git a/xbmc/dialogs/GUIDialogMediaSource.cpp b/xbmc/dialogs/GUIDialogMediaSource.cpp index 72b80bff53..0afbc2d060 100644 --- a/xbmc/dialogs/GUIDialogMediaSource.cpp +++ b/xbmc/dialogs/GUIDialogMediaSource.cpp @@ -9,6 +9,7 @@ #include "GUIDialogMediaSource.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIDialogFileBrowser.h" #include "GUIDialogYesNo.h" #include "PasswordManager.h" diff --git a/xbmc/dialogs/GUIDialogSelect.cpp b/xbmc/dialogs/GUIDialogSelect.cpp index c6add4bd16..0f99e2765b 100644 --- a/xbmc/dialogs/GUIDialogSelect.cpp +++ b/xbmc/dialogs/GUIDialogSelect.cpp @@ -9,6 +9,7 @@ #include "GUIDialogSelect.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/GUIMessage.h" #include "guilib/LocalizeStrings.h" #include "input/actions/ActionIDs.h" diff --git a/xbmc/dialogs/GUIDialogSimpleMenu.cpp b/xbmc/dialogs/GUIDialogSimpleMenu.cpp index 0d4d11a830..61016f477a 100644 --- a/xbmc/dialogs/GUIDialogSimpleMenu.cpp +++ b/xbmc/dialogs/GUIDialogSimpleMenu.cpp @@ -10,6 +10,7 @@ #include "GUIDialogSimpleMenu.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIDialogSelect.h" #include "ServiceBroker.h" #include "URL.h" @@ -25,8 +26,11 @@ #include "utils/URIUtils.h" #include "utils/Variant.h" #include "utils/log.h" +#include "video/VideoFileItemClassify.h" #include "video/VideoInfoTag.h" +using namespace KODI; + namespace { class CGetDirectoryItems : public IRunnable @@ -54,7 +58,7 @@ bool CGUIDialogSimpleMenu::ShowPlaySelection(CFileItem& item) if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_DISC_PLAYBACK) != BD_PLAYBACK_SIMPLE_MENU) return true; - if (item.IsBDFile()) + if (VIDEO::IsBDFile(item)) { std::string root = URIUtils::GetParentPath(item.GetDynPath()); URIUtils::RemoveSlashAtEnd(root); diff --git a/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp b/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp index 98714d38dc..24a0675c40 100644 --- a/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp +++ b/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp @@ -9,6 +9,7 @@ #include "GUIDialogSmartPlaylistEditor.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIDialogContextMenu.h" #include "GUIDialogSelect.h" #include "GUIDialogSmartPlaylistRule.h" diff --git a/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp b/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp index 671219bc38..9040f48340 100644 --- a/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp +++ b/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp @@ -9,6 +9,7 @@ #include "GUIDialogSmartPlaylistRule.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIDialogFileBrowser.h" #include "GUIDialogSelect.h" #include "ServiceBroker.h" diff --git a/xbmc/events/windows/GUIViewStateEventLog.cpp b/xbmc/events/windows/GUIViewStateEventLog.cpp index 1f6dd6654f..8734f12571 100644 --- a/xbmc/events/windows/GUIViewStateEventLog.cpp +++ b/xbmc/events/windows/GUIViewStateEventLog.cpp @@ -9,6 +9,7 @@ #include "GUIViewStateEventLog.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/WindowIDs.h" #include "view/ViewState.h" #include "windowing/GraphicContext.h" diff --git a/xbmc/events/windows/GUIWindowEventLog.cpp b/xbmc/events/windows/GUIWindowEventLog.cpp index fdd9a37b00..90e8c29f71 100644 --- a/xbmc/events/windows/GUIWindowEventLog.cpp +++ b/xbmc/events/windows/GUIWindowEventLog.cpp @@ -9,6 +9,7 @@ #include "GUIWindowEventLog.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" #include "URL.h" diff --git a/xbmc/favourites/FavouritesService.h b/xbmc/favourites/FavouritesService.h index ccda06253d..468961ecb3 100644 --- a/xbmc/favourites/FavouritesService.h +++ b/xbmc/favourites/FavouritesService.h @@ -9,6 +9,7 @@ #pragma once #include "FileItem.h" +#include "FileItemList.h" #include "threads/CriticalSection.h" #include "utils/EventStream.h" diff --git a/xbmc/favourites/GUIViewStateFavourites.cpp b/xbmc/favourites/GUIViewStateFavourites.cpp index 7bb5ff1195..3343167b5c 100644 --- a/xbmc/favourites/GUIViewStateFavourites.cpp +++ b/xbmc/favourites/GUIViewStateFavourites.cpp @@ -8,7 +8,7 @@ #include "GUIViewStateFavourites.h" -#include "FileItem.h" +#include "FileItemList.h" #include "guilib/WindowIDs.h" CGUIViewStateFavourites::CGUIViewStateFavourites(const CFileItemList& items) : CGUIViewState(items) diff --git a/xbmc/filesystem/AddonsDirectory.cpp b/xbmc/filesystem/AddonsDirectory.cpp index 1439ae054b..aba97cae08 100644 --- a/xbmc/filesystem/AddonsDirectory.cpp +++ b/xbmc/filesystem/AddonsDirectory.cpp @@ -9,6 +9,7 @@ #include "AddonsDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "addons/AddonDatabase.h" @@ -789,29 +790,27 @@ void CAddonsDirectory::GenerateAddonListing(const CURL& path, addon->Version()); bool disabled = CServiceBroker::GetAddonMgr().IsAddonDisabled(addon->ID()); - std::function<bool(bool)> CheckOutdatedOrUpdate = [&](bool checkOutdated) -> bool { - auto mapEntry = addonsWithUpdate.find(addon->ID()); - if (mapEntry != addonsWithUpdate.end()) - { - const std::shared_ptr<IAddon>& checkedObject = - checkOutdated ? mapEntry->second.m_installed : mapEntry->second.m_update; - - return (checkedObject->Origin() == addon->Origin() && - checkedObject->Version() == addon->Version()); - } - return false; - }; - - bool isUpdate = CheckOutdatedOrUpdate(false); // check if it's an available update - bool hasUpdate = CheckOutdatedOrUpdate(true); // check if it's an outdated addon - + bool isUpdate{false}; + bool hasUpdate{false}; std::string validUpdateVersion; std::string validUpdateOrigin; - if (hasUpdate) + + auto _ = addonsWithUpdate.find(addon->ID()); + if (_ != addonsWithUpdate.end()) { - auto mapEntry = addonsWithUpdate.find(addon->ID()); - validUpdateVersion = mapEntry->second.m_update->Version().asString(); - validUpdateOrigin = mapEntry->second.m_update->Origin(); + auto [installed, update] = _->second; + + auto CheckAddon = [&addon](const std::shared_ptr<IAddon>& _) + { return _->Origin() == addon->Origin() && _->Version() == addon->Version(); }; + + isUpdate = CheckAddon(update); // check if listed add-on is update to an installed add-on + hasUpdate = CheckAddon(installed); // check if installed add-on has an update available + + if (hasUpdate) + { + validUpdateVersion = update->Version().asString(); + validUpdateOrigin = update->Origin(); + } } bool fromOfficialRepo = CAddonRepos::IsFromOfficialRepo(addon, CheckAddonPath::CHOICE_NO); diff --git a/xbmc/filesystem/AudioBookFileDirectory.cpp b/xbmc/filesystem/AudioBookFileDirectory.cpp index 4b56c6ccc2..2ca214c74e 100644 --- a/xbmc/filesystem/AudioBookFileDirectory.cpp +++ b/xbmc/filesystem/AudioBookFileDirectory.cpp @@ -8,6 +8,7 @@ #include "AudioBookFileDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "TextureDatabase.h" #include "URL.h" #include "Util.h" diff --git a/xbmc/filesystem/BlurayCallback.cpp b/xbmc/filesystem/BlurayCallback.cpp index 4849eef1a7..72b745381a 100644 --- a/xbmc/filesystem/BlurayCallback.cpp +++ b/xbmc/filesystem/BlurayCallback.cpp @@ -9,6 +9,7 @@ #include "BlurayCallback.h" #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/Directory.h" #include "filesystem/File.h" #include "utils/URIUtils.h" diff --git a/xbmc/filesystem/BlurayDirectory.cpp b/xbmc/filesystem/BlurayDirectory.cpp index b6c339a110..322b662fd9 100644 --- a/xbmc/filesystem/BlurayDirectory.cpp +++ b/xbmc/filesystem/BlurayDirectory.cpp @@ -9,6 +9,7 @@ #include "File.h" #include "FileItem.h" +#include "FileItemList.h" #include "LangInfo.h" #include "URL.h" #include "filesystem/BlurayCallback.h" diff --git a/xbmc/filesystem/CDDADirectory.cpp b/xbmc/filesystem/CDDADirectory.cpp index 9b6beaaeea..8520347108 100644 --- a/xbmc/filesystem/CDDADirectory.cpp +++ b/xbmc/filesystem/CDDADirectory.cpp @@ -10,6 +10,7 @@ #include "File.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "music/MusicDatabase.h" #include "storage/MediaManager.h" diff --git a/xbmc/filesystem/DAVDirectory.cpp b/xbmc/filesystem/DAVDirectory.cpp index 0a203e7807..08905fca31 100644 --- a/xbmc/filesystem/DAVDirectory.cpp +++ b/xbmc/filesystem/DAVDirectory.cpp @@ -12,6 +12,7 @@ #include "DAVCommon.h" #include "DAVFile.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" diff --git a/xbmc/filesystem/Directorization.h b/xbmc/filesystem/Directorization.h index f413635e6d..d41c71bae9 100644 --- a/xbmc/filesystem/Directorization.h +++ b/xbmc/filesystem/Directorization.h @@ -9,6 +9,7 @@ #pragma once #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "utils/CharsetConverter.h" #include "utils/StringUtils.h" diff --git a/xbmc/filesystem/Directory.cpp b/xbmc/filesystem/Directory.cpp index fbcdb4d0d4..cfa0fd9b53 100644 --- a/xbmc/filesystem/Directory.cpp +++ b/xbmc/filesystem/Directory.cpp @@ -12,6 +12,7 @@ #include "DirectoryFactory.h" #include "FileDirectoryFactory.h" #include "FileItem.h" +#include "FileItemList.h" #include "PasswordManager.h" #include "ServiceBroker.h" #include "URL.h" @@ -25,7 +26,9 @@ #include "utils/JobManager.h" #include "utils/URIUtils.h" #include "utils/log.h" +#include "video/VideoFileItemClassify.h" +using namespace KODI; using namespace XFILE; using namespace std::chrono_literals; @@ -282,7 +285,8 @@ bool CDirectory::GetDirectory(const CURL& url, // Should any of the files we read be treated as a directory? // Disable for database folders, as they already contain the extracted items - if (!(hints.flags & DIR_FLAG_NO_FILE_DIRS) && !items.IsMusicDb() && !items.IsVideoDb() && !items.IsSmartPlayList()) + if (!(hints.flags & DIR_FLAG_NO_FILE_DIRS) && !items.IsMusicDb() && !VIDEO::IsVideoDb(items) && + !items.IsSmartPlayList()) FilterFileDirectories(items, hints.mask); // Correct items for path substitution diff --git a/xbmc/filesystem/DirectoryCache.cpp b/xbmc/filesystem/DirectoryCache.cpp index f3fd1fb7ae..f1053a904b 100644 --- a/xbmc/filesystem/DirectoryCache.cpp +++ b/xbmc/filesystem/DirectoryCache.cpp @@ -10,6 +10,7 @@ #include "Directory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" diff --git a/xbmc/filesystem/EventsDirectory.cpp b/xbmc/filesystem/EventsDirectory.cpp index d21261944b..bc8cfdf0af 100644 --- a/xbmc/filesystem/EventsDirectory.cpp +++ b/xbmc/filesystem/EventsDirectory.cpp @@ -10,6 +10,7 @@ #include "EventsDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "events/EventLog.h" diff --git a/xbmc/filesystem/FTPDirectory.cpp b/xbmc/filesystem/FTPDirectory.cpp index 46d3d7d748..2b7117a7a8 100644 --- a/xbmc/filesystem/FTPDirectory.cpp +++ b/xbmc/filesystem/FTPDirectory.cpp @@ -11,6 +11,7 @@ #include "CurlFile.h" #include "FTPParse.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "utils/CharsetConverter.h" #include "utils/StringUtils.h" diff --git a/xbmc/filesystem/HTTPDirectory.cpp b/xbmc/filesystem/HTTPDirectory.cpp index 0097b7f15c..1db70696d1 100644 --- a/xbmc/filesystem/HTTPDirectory.cpp +++ b/xbmc/filesystem/HTTPDirectory.cpp @@ -10,6 +10,7 @@ #include "CurlFile.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "settings/AdvancedSettings.h" diff --git a/xbmc/filesystem/ISO9660Directory.cpp b/xbmc/filesystem/ISO9660Directory.cpp index 542f12c577..a396b996b0 100644 --- a/xbmc/filesystem/ISO9660Directory.cpp +++ b/xbmc/filesystem/ISO9660Directory.cpp @@ -9,6 +9,7 @@ #include "ISO9660Directory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "utils/URIUtils.h" diff --git a/xbmc/filesystem/LibraryDirectory.cpp b/xbmc/filesystem/LibraryDirectory.cpp index 8f814950ae..ec5a16bfc0 100644 --- a/xbmc/filesystem/LibraryDirectory.cpp +++ b/xbmc/filesystem/LibraryDirectory.cpp @@ -10,6 +10,7 @@ #include "Directory.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "SmartPlaylistDirectory.h" #include "URL.h" diff --git a/xbmc/filesystem/MultiPathDirectory.cpp b/xbmc/filesystem/MultiPathDirectory.cpp index 4cdcfcc4ce..b57dd98427 100644 --- a/xbmc/filesystem/MultiPathDirectory.cpp +++ b/xbmc/filesystem/MultiPathDirectory.cpp @@ -10,6 +10,7 @@ #include "Directory.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "Util.h" diff --git a/xbmc/filesystem/MusicDatabaseDirectory.cpp b/xbmc/filesystem/MusicDatabaseDirectory.cpp index f998d559f7..0365f86617 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory.cpp @@ -9,6 +9,7 @@ #include "MusicDatabaseDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "MusicDatabaseDirectory/QueryParams.h" #include "ServiceBroker.h" #include "filesystem/File.h" diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.cpp index 00e1bce6f3..cb143c1ecc 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.cpp @@ -25,6 +25,7 @@ #include "DirectoryNodeSongTop100.h" #include "DirectoryNodeTop100.h" #include "FileItem.h" +#include "FileItemList.h" #include "QueryParams.h" #include "URL.h" #include "utils/StringUtils.h" diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumRecentlyAdded.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumRecentlyAdded.cpp index f274b59341..013c30bd65 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumRecentlyAdded.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumRecentlyAdded.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeAlbumRecentlyAdded.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/LocalizeStrings.h" #include "music/MusicDatabase.h" #include "utils/StringUtils.h" diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumRecentlyPlayed.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumRecentlyPlayed.cpp index 77940c27f1..8080d5e7e0 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumRecentlyPlayed.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumRecentlyPlayed.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeAlbumRecentlyPlayed.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/LocalizeStrings.h" #include "music/MusicDatabase.h" #include "utils/StringUtils.h" diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumTop100.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumTop100.cpp index 88ffaff77a..753b756ac8 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumTop100.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumTop100.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeAlbumTop100.h" #include "FileItem.h" +#include "FileItemList.h" #include "music/MusicDatabase.h" #include "utils/StringUtils.h" diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp index fefeb6d666..cca955e4b7 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeOverview.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/LocalizeStrings.h" #include "music/MusicDatabase.h" #include "utils/StringUtils.h" diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeTop100.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeTop100.cpp index fff9228b58..36bacfeb55 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeTop100.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeTop100.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeTop100.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/LocalizeStrings.h" #include "utils/StringUtils.h" diff --git a/xbmc/filesystem/MusicFileDirectory.cpp b/xbmc/filesystem/MusicFileDirectory.cpp index b3c7749c47..51340b54eb 100644 --- a/xbmc/filesystem/MusicFileDirectory.cpp +++ b/xbmc/filesystem/MusicFileDirectory.cpp @@ -9,6 +9,7 @@ #include "MusicFileDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "guilib/LocalizeStrings.h" #include "utils/StringUtils.h" diff --git a/xbmc/filesystem/MusicSearchDirectory.cpp b/xbmc/filesystem/MusicSearchDirectory.cpp index 1d1868ab1a..2f8c8200cc 100644 --- a/xbmc/filesystem/MusicSearchDirectory.cpp +++ b/xbmc/filesystem/MusicSearchDirectory.cpp @@ -9,6 +9,7 @@ #include "MusicSearchDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "guilib/LocalizeStrings.h" #include "music/MusicDatabase.h" diff --git a/xbmc/filesystem/NFSDirectory.cpp b/xbmc/filesystem/NFSDirectory.cpp index 7feba534c7..6d3588dccc 100644 --- a/xbmc/filesystem/NFSDirectory.cpp +++ b/xbmc/filesystem/NFSDirectory.cpp @@ -13,6 +13,7 @@ #endif #include "FileItem.h" +#include "FileItemList.h" #include "NFSDirectory.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" diff --git a/xbmc/filesystem/PlaylistDirectory.cpp b/xbmc/filesystem/PlaylistDirectory.cpp index 8be88dc581..f656c77dab 100644 --- a/xbmc/filesystem/PlaylistDirectory.cpp +++ b/xbmc/filesystem/PlaylistDirectory.cpp @@ -9,6 +9,7 @@ #include "PlaylistDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "PlayListPlayer.h" #include "ServiceBroker.h" #include "URL.h" diff --git a/xbmc/filesystem/PlaylistFileDirectory.cpp b/xbmc/filesystem/PlaylistFileDirectory.cpp index 2bdb243680..108c9c9a65 100644 --- a/xbmc/filesystem/PlaylistFileDirectory.cpp +++ b/xbmc/filesystem/PlaylistFileDirectory.cpp @@ -9,6 +9,7 @@ #include "PlaylistFileDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "filesystem/File.h" #include "playlists/PlayList.h" diff --git a/xbmc/filesystem/PluginDirectory.cpp b/xbmc/filesystem/PluginDirectory.cpp index cf3ded1286..4269fa4236 100644 --- a/xbmc/filesystem/PluginDirectory.cpp +++ b/xbmc/filesystem/PluginDirectory.cpp @@ -9,6 +9,7 @@ #include "PluginDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "addons/AddonInstaller.h" diff --git a/xbmc/filesystem/RSSDirectory.cpp b/xbmc/filesystem/RSSDirectory.cpp index 65bc876c6c..ac0a704221 100644 --- a/xbmc/filesystem/RSSDirectory.cpp +++ b/xbmc/filesystem/RSSDirectory.cpp @@ -10,6 +10,7 @@ #include "CurlFile.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "settings/AdvancedSettings.h" diff --git a/xbmc/filesystem/ResourceDirectory.cpp b/xbmc/filesystem/ResourceDirectory.cpp index c3623d0ce0..6526fb56be 100644 --- a/xbmc/filesystem/ResourceDirectory.cpp +++ b/xbmc/filesystem/ResourceDirectory.cpp @@ -9,6 +9,7 @@ #include "ResourceDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "filesystem/Directory.h" #include "filesystem/ResourceFile.h" diff --git a/xbmc/filesystem/SmartPlaylistDirectory.cpp b/xbmc/filesystem/SmartPlaylistDirectory.cpp index a45e796071..b3d361ecc2 100644 --- a/xbmc/filesystem/SmartPlaylistDirectory.cpp +++ b/xbmc/filesystem/SmartPlaylistDirectory.cpp @@ -9,6 +9,7 @@ #include "SmartPlaylistDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "filesystem/Directory.h" #include "filesystem/File.h" diff --git a/xbmc/filesystem/SourcesDirectory.cpp b/xbmc/filesystem/SourcesDirectory.cpp index b83ee2ed49..0f36fbb88e 100644 --- a/xbmc/filesystem/SourcesDirectory.cpp +++ b/xbmc/filesystem/SourcesDirectory.cpp @@ -9,6 +9,7 @@ #include "SourcesDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "Util.h" @@ -19,7 +20,9 @@ #include "storage/MediaManager.h" #include "utils/FileUtils.h" #include "utils/URIUtils.h" +#include "video/VideoFileItemClassify.h" +using namespace KODI; using namespace XFILE; CSourcesDirectory::CSourcesDirectory(void) = default; @@ -68,10 +71,8 @@ bool CSourcesDirectory::GetDirectory(const VECSOURCES &sources, CFileItemList &i else if ( pItem->IsPath("special://musicplaylists/") || pItem->IsPath("special://videoplaylists/")) strIcon = "DefaultPlaylist.png"; - else if ( pItem->IsVideoDb() - || pItem->IsMusicDb() - || pItem->IsPlugin() - || pItem->IsPath("musicsearch://")) + else if (VIDEO::IsVideoDb(*pItem) || pItem->IsMusicDb() || pItem->IsPlugin() || + pItem->IsPath("musicsearch://")) strIcon = "DefaultFolder.png"; else if (pItem->IsRemote()) strIcon = "DefaultNetwork.png"; diff --git a/xbmc/filesystem/SpecialProtocolDirectory.cpp b/xbmc/filesystem/SpecialProtocolDirectory.cpp index e4a970ea99..d1af8b0345 100644 --- a/xbmc/filesystem/SpecialProtocolDirectory.cpp +++ b/xbmc/filesystem/SpecialProtocolDirectory.cpp @@ -10,6 +10,7 @@ #include "Directory.h" #include "FileItem.h" +#include "FileItemList.h" #include "SpecialProtocol.h" #include "URL.h" #include "utils/URIUtils.h" diff --git a/xbmc/filesystem/StackDirectory.cpp b/xbmc/filesystem/StackDirectory.cpp index 58cbe9dff9..9b6aae53b0 100644 --- a/xbmc/filesystem/StackDirectory.cpp +++ b/xbmc/filesystem/StackDirectory.cpp @@ -9,6 +9,7 @@ #include "StackDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "settings/AdvancedSettings.h" diff --git a/xbmc/filesystem/UDFDirectory.cpp b/xbmc/filesystem/UDFDirectory.cpp index 236b281303..b22b496d1d 100644 --- a/xbmc/filesystem/UDFDirectory.cpp +++ b/xbmc/filesystem/UDFDirectory.cpp @@ -12,6 +12,7 @@ #include "UDFDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "Util.h" #include "filesystem/UDFBlockInput.h" diff --git a/xbmc/filesystem/UPnPDirectory.cpp b/xbmc/filesystem/UPnPDirectory.cpp index 4d6608acfa..2b2af57598 100644 --- a/xbmc/filesystem/UPnPDirectory.cpp +++ b/xbmc/filesystem/UPnPDirectory.cpp @@ -13,6 +13,7 @@ #include "UPnPDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "network/upnp/UPnP.h" diff --git a/xbmc/filesystem/VideoDatabaseDirectory.cpp b/xbmc/filesystem/VideoDatabaseDirectory.cpp index 2c9caa7080..4242b095ce 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory.cpp @@ -10,6 +10,7 @@ #include "File.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "VideoDatabaseDirectory/QueryParams.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp index b62839c9bc..f181b4514a 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp @@ -24,6 +24,7 @@ #include "DirectoryNodeTitleTvShows.h" #include "DirectoryNodeTvShowsOverview.h" #include "FileItem.h" +#include "FileItemList.h" #include "QueryParams.h" #include "URL.h" #include "utils/StringUtils.h" diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeEpisodes.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeEpisodes.cpp index 9f629baa69..c75471cb0f 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeEpisodes.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeEpisodes.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeEpisodes.h" #include "FileItem.h" +#include "FileItemList.h" #include "QueryParams.h" #include "video/VideoDatabase.h" diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeInProgressTvShows.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeInProgressTvShows.cpp index 044f8b3c74..f0a652232e 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeInProgressTvShows.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeInProgressTvShows.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeInProgressTvShows.h" #include "FileItem.h" +#include "FileItemList.h" #include "video/VideoDatabase.h" using namespace XFILE::VIDEODATABASEDIRECTORY; diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp index 9f415d09da..33d70051d8 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeMoviesOverview.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/LocalizeStrings.h" #include "utils/StringUtils.h" #include "video/VideoDatabase.h" diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMusicVideosOverview.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMusicVideosOverview.cpp index b71d8f1d2b..9c7290abc5 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMusicVideosOverview.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMusicVideosOverview.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeMusicVideosOverview.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/LocalizeStrings.h" #include "utils/StringUtils.h" #include "video/VideoDbUrl.h" diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp index b52ae24dc5..0aeed45edc 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeOverview.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "guilib/LocalizeStrings.h" #include "settings/Settings.h" diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedEpisodes.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedEpisodes.cpp index fe50dad926..317c761002 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedEpisodes.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedEpisodes.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeRecentlyAddedEpisodes.h" #include "FileItem.h" +#include "FileItemList.h" #include "video/VideoDatabase.h" using namespace XFILE::VIDEODATABASEDIRECTORY; diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMovies.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMovies.cpp index 202d6f7b4a..41b372beb6 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMovies.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMovies.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeRecentlyAddedMovies.h" #include "FileItem.h" +#include "FileItemList.h" #include "video/VideoDatabase.h" using namespace XFILE::VIDEODATABASEDIRECTORY; diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMusicVideos.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMusicVideos.cpp index d8ba5ef74d..2f57643b43 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMusicVideos.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMusicVideos.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeRecentlyAddedMusicVideos.h" #include "FileItem.h" +#include "FileItemList.h" #include "video/VideoDatabase.h" using namespace XFILE::VIDEODATABASEDIRECTORY; diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp index 45a83cee8f..0e82fcca9e 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeTitleMovies.h" #include "FileItem.h" +#include "FileItemList.h" #include "QueryParams.h" #include "video/VideoDatabase.h" diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMusicVideos.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMusicVideos.cpp index 95fe30010b..d35398b153 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMusicVideos.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMusicVideos.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeTitleMusicVideos.h" #include "FileItem.h" +#include "FileItemList.h" #include "QueryParams.h" #include "video/VideoDatabase.h" diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleTvShows.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleTvShows.cpp index b1a247ca7f..52f903fffd 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleTvShows.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleTvShows.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeTitleTvShows.h" #include "FileItem.h" +#include "FileItemList.h" #include "QueryParams.h" #include "video/VideoDatabase.h" diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTvShowsOverview.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTvShowsOverview.cpp index 07e5ff4aee..5a490a53d7 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTvShowsOverview.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTvShowsOverview.cpp @@ -9,6 +9,7 @@ #include "DirectoryNodeTvShowsOverview.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/LocalizeStrings.h" #include "utils/StringUtils.h" #include "video/VideoDbUrl.h" diff --git a/xbmc/filesystem/VirtualDirectory.cpp b/xbmc/filesystem/VirtualDirectory.cpp index 4fb0205d1e..f764645cf9 100644 --- a/xbmc/filesystem/VirtualDirectory.cpp +++ b/xbmc/filesystem/VirtualDirectory.cpp @@ -11,6 +11,7 @@ #include "Directory.h" #include "DirectoryFactory.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "SourcesDirectory.h" #include "URL.h" diff --git a/xbmc/filesystem/ZeroconfDirectory.cpp b/xbmc/filesystem/ZeroconfDirectory.cpp index f34b6b2f1f..d05184e394 100644 --- a/xbmc/filesystem/ZeroconfDirectory.cpp +++ b/xbmc/filesystem/ZeroconfDirectory.cpp @@ -10,6 +10,7 @@ #include "Directory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "network/ZeroconfBrowser.h" #include "utils/URIUtils.h" diff --git a/xbmc/filesystem/test/TestDirectory.cpp b/xbmc/filesystem/test/TestDirectory.cpp index e99408c9dc..8f65b06356 100644 --- a/xbmc/filesystem/test/TestDirectory.cpp +++ b/xbmc/filesystem/test/TestDirectory.cpp @@ -7,6 +7,7 @@ */ #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/Directory.h" #include "filesystem/IDirectory.h" #include "filesystem/SpecialProtocol.h" diff --git a/xbmc/filesystem/test/TestHTTPDirectory.cpp b/xbmc/filesystem/test/TestHTTPDirectory.cpp index 773630770b..8288bda46f 100644 --- a/xbmc/filesystem/test/TestHTTPDirectory.cpp +++ b/xbmc/filesystem/test/TestHTTPDirectory.cpp @@ -7,6 +7,7 @@ */ #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "filesystem/CurlFile.h" #include "filesystem/HTTPDirectory.h" diff --git a/xbmc/filesystem/test/TestZipFile.cpp b/xbmc/filesystem/test/TestZipFile.cpp index 3ff518b8dc..ffb4478cdd 100644 --- a/xbmc/filesystem/test/TestZipFile.cpp +++ b/xbmc/filesystem/test/TestZipFile.cpp @@ -7,6 +7,7 @@ */ #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "filesystem/Directory.h" diff --git a/xbmc/games/addons/GameClientProperties.cpp b/xbmc/games/addons/GameClientProperties.cpp index f3d97858bd..ae081afa92 100644 --- a/xbmc/games/addons/GameClientProperties.cpp +++ b/xbmc/games/addons/GameClientProperties.cpp @@ -9,6 +9,7 @@ #include "GameClientProperties.h" #include "FileItem.h" +#include "FileItemList.h" #include "GameClient.h" #include "ServiceBroker.h" #include "addons/AddonManager.h" diff --git a/xbmc/games/agents/windows/GUIAgentControllerList.cpp b/xbmc/games/agents/windows/GUIAgentControllerList.cpp index 55bb3e2296..7da49e72d2 100644 --- a/xbmc/games/agents/windows/GUIAgentControllerList.cpp +++ b/xbmc/games/agents/windows/GUIAgentControllerList.cpp @@ -9,6 +9,7 @@ #include "GUIAgentControllerList.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIAgentDefines.h" #include "GUIAgentWindow.h" #include "ServiceBroker.h" diff --git a/xbmc/games/controllers/dialogs/ControllerInstaller.cpp b/xbmc/games/controllers/dialogs/ControllerInstaller.cpp index 9b0fe6fc87..18f7634a01 100644 --- a/xbmc/games/controllers/dialogs/ControllerInstaller.cpp +++ b/xbmc/games/controllers/dialogs/ControllerInstaller.cpp @@ -9,6 +9,7 @@ #include "ControllerInstaller.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "addons/Addon.h" #include "addons/AddonInstaller.h" diff --git a/xbmc/games/controllers/dialogs/ControllerSelect.cpp b/xbmc/games/controllers/dialogs/ControllerSelect.cpp index 2ef9941dea..8219731120 100644 --- a/xbmc/games/controllers/dialogs/ControllerSelect.cpp +++ b/xbmc/games/controllers/dialogs/ControllerSelect.cpp @@ -9,6 +9,7 @@ #include "ControllerSelect.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "dialogs/GUIDialogSelect.h" #include "games/controllers/Controller.h" diff --git a/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp b/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp index f4c754aee0..08d6b71ffb 100644 --- a/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp +++ b/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp @@ -9,6 +9,7 @@ #include "GUIDialogSelectGameClient.h" #include "FileItem.h" +#include "FileItemList.h" #include "dialogs/GUIDialogSelect.h" #include "filesystem/AddonsDirectory.h" #include "games/addons/GameClient.h" diff --git a/xbmc/games/dialogs/osd/DialogGameSaves.cpp b/xbmc/games/dialogs/osd/DialogGameSaves.cpp index a2c08d606f..239b78ab4e 100644 --- a/xbmc/games/dialogs/osd/DialogGameSaves.cpp +++ b/xbmc/games/dialogs/osd/DialogGameSaves.cpp @@ -9,6 +9,7 @@ #include "DialogGameSaves.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "addons/Addon.h" #include "addons/AddonManager.h" diff --git a/xbmc/games/dialogs/osd/DialogGameStretchMode.cpp b/xbmc/games/dialogs/osd/DialogGameStretchMode.cpp index 98c1e077e8..67f4cad1ff 100644 --- a/xbmc/games/dialogs/osd/DialogGameStretchMode.cpp +++ b/xbmc/games/dialogs/osd/DialogGameStretchMode.cpp @@ -9,6 +9,7 @@ #include "DialogGameStretchMode.h" #include "FileItem.h" +#include "FileItemList.h" #include "cores/RetroPlayer/RetroPlayerUtils.h" #include "cores/RetroPlayer/guibridge/GUIGameVideoHandle.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/games/dialogs/osd/DialogGameVideoFilter.h b/xbmc/games/dialogs/osd/DialogGameVideoFilter.h index 237720d65d..6c659da6e0 100644 --- a/xbmc/games/dialogs/osd/DialogGameVideoFilter.h +++ b/xbmc/games/dialogs/osd/DialogGameVideoFilter.h @@ -10,6 +10,7 @@ #include "DialogGameVideoSelect.h" #include "FileItem.h" +#include "FileItemList.h" namespace KODI { diff --git a/xbmc/games/dialogs/osd/DialogGameVideoRotation.cpp b/xbmc/games/dialogs/osd/DialogGameVideoRotation.cpp index 7037a6b35c..3fe6baa778 100644 --- a/xbmc/games/dialogs/osd/DialogGameVideoRotation.cpp +++ b/xbmc/games/dialogs/osd/DialogGameVideoRotation.cpp @@ -9,6 +9,7 @@ #include "DialogGameVideoRotation.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/LocalizeStrings.h" #include "guilib/WindowIDs.h" #include "settings/GameSettings.h" diff --git a/xbmc/games/dialogs/osd/DialogGameVideoSelect.cpp b/xbmc/games/dialogs/osd/DialogGameVideoSelect.cpp index a69b26f772..0bf1529244 100644 --- a/xbmc/games/dialogs/osd/DialogGameVideoSelect.cpp +++ b/xbmc/games/dialogs/osd/DialogGameVideoSelect.cpp @@ -9,6 +9,7 @@ #include "DialogGameVideoSelect.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "cores/RetroPlayer/guibridge/GUIGameRenderManager.h" #include "cores/RetroPlayer/guibridge/GUIGameVideoHandle.h" diff --git a/xbmc/games/dialogs/osd/DialogInGameSaves.h b/xbmc/games/dialogs/osd/DialogInGameSaves.h index 5c1c3176c7..8fdb7b0b6c 100644 --- a/xbmc/games/dialogs/osd/DialogInGameSaves.h +++ b/xbmc/games/dialogs/osd/DialogInGameSaves.h @@ -10,6 +10,7 @@ #include "DialogGameVideoSelect.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/GUIListItem.h" #include <string> diff --git a/xbmc/games/ports/guicontrols/GUIActivePortList.cpp b/xbmc/games/ports/guicontrols/GUIActivePortList.cpp index 851ca86266..f0e89f6e8d 100644 --- a/xbmc/games/ports/guicontrols/GUIActivePortList.cpp +++ b/xbmc/games/ports/guicontrols/GUIActivePortList.cpp @@ -9,6 +9,7 @@ #include "GUIActivePortList.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "addons/AddonEvents.h" #include "addons/AddonManager.h" diff --git a/xbmc/games/ports/windows/GUIPortList.cpp b/xbmc/games/ports/windows/GUIPortList.cpp index c0e46e0bac..9db78747be 100644 --- a/xbmc/games/ports/windows/GUIPortList.cpp +++ b/xbmc/games/ports/windows/GUIPortList.cpp @@ -9,6 +9,7 @@ #include "GUIPortList.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPortDefines.h" #include "GUIPortWindow.h" #include "ServiceBroker.h" diff --git a/xbmc/games/windows/GUIViewStateWindowGames.cpp b/xbmc/games/windows/GUIViewStateWindowGames.cpp index e388d8ff83..3f45122ac7 100644 --- a/xbmc/games/windows/GUIViewStateWindowGames.cpp +++ b/xbmc/games/windows/GUIViewStateWindowGames.cpp @@ -9,6 +9,7 @@ #include "GUIViewStateWindowGames.h" #include "FileItem.h" +#include "FileItemList.h" #include "games/GameUtils.h" #include "guilib/LocalizeStrings.h" #include "guilib/WindowIDs.h" diff --git a/xbmc/games/windows/GUIWindowGames.cpp b/xbmc/games/windows/GUIWindowGames.cpp index a74186db84..2d9eb600db 100644 --- a/xbmc/games/windows/GUIWindowGames.cpp +++ b/xbmc/games/windows/GUIWindowGames.cpp @@ -9,6 +9,7 @@ #include "GUIWindowGames.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "ServiceBroker.h" #include "URL.h" diff --git a/xbmc/guilib/GUIBaseContainer.cpp b/xbmc/guilib/GUIBaseContainer.cpp index 897459790d..65d604c18f 100644 --- a/xbmc/guilib/GUIBaseContainer.cpp +++ b/xbmc/guilib/GUIBaseContainer.cpp @@ -9,6 +9,7 @@ #include "GUIBaseContainer.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "GUIListItemLayout.h" #include "GUIMessage.h" diff --git a/xbmc/guilib/GUIControl.cpp b/xbmc/guilib/GUIControl.cpp index 689c55f257..0c6a902ebb 100644 --- a/xbmc/guilib/GUIControl.cpp +++ b/xbmc/guilib/GUIControl.cpp @@ -180,6 +180,10 @@ void CGUIControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregio // 3. reset the animation transform void CGUIControl::DoRender() { + if (IsControlRenderable() && + !m_renderRegion.Intersects(CServiceBroker::GetWinSystem()->GetGfxContext().GetScissors())) + return; + if (IsVisible() && !m_isCulled) { bool hasStereo = @@ -954,6 +958,24 @@ void CGUIControl::UpdateControlStats() } } +bool CGUIControl::IsControlRenderable() +{ + switch (ControlType) + { + case GUICONTAINER_EPGGRID: + case GUICONTAINER_FIXEDLIST: + case GUICONTAINER_LIST: + case GUICONTAINER_PANEL: + case GUICONTAINER_WRAPLIST: + case GUICONTROL_GROUP: + case GUICONTROL_GROUPLIST: + case GUICONTROL_LISTGROUP: + return false; + default: + return true; + } +} + void CGUIControl::SetHitRect(const CRect& rect, const UTILS::COLOR::Color& color) { m_hitRect = rect; diff --git a/xbmc/guilib/GUIControl.h b/xbmc/guilib/GUIControl.h index 4cedee0761..a57f02243b 100644 --- a/xbmc/guilib/GUIControl.h +++ b/xbmc/guilib/GUIControl.h @@ -306,6 +306,11 @@ public: }; GUICONTROLTYPES GetControlType() const { return ControlType; } + /*! \brief Test whether the control is "drawable" (not a group or similar) + \return true if the control has textures/labels it wants to render + */ + bool IsControlRenderable(); + enum GUIVISIBLE { HIDDEN = 0, DELAYED, VISIBLE }; enum GUISCROLLVALUE { FOCUS = 0, NEVER, ALWAYS }; diff --git a/xbmc/guilib/GUIFont.cpp b/xbmc/guilib/GUIFont.cpp index 784dd75971..bf0c014a0a 100644 --- a/xbmc/guilib/GUIFont.cpp +++ b/xbmc/guilib/GUIFont.cpp @@ -234,18 +234,18 @@ void CGUIFont::DrawScrollingText(float x, shadowColors.emplace_back((renderColor & 0xff000000) != 0 ? shadowColor : 0); for (float dx = -offset; dx < maxWidth; dx += scrollInfo.m_totalWidth) { - m_font->DrawTextInternal(context, x + dx + 1, y + 1, shadowColors, text, alignment, - textPixelWidth, scroll); - m_font->DrawTextInternal(context, x + dx + scrollInfo.m_textWidth + 1, y + 1, shadowColors, - scrollInfo.m_suffix, alignment, suffixPixelWidth, scroll); + m_font->DrawTextInternal(context, x + 1, y + 1, shadowColors, text, alignment, textPixelWidth, + scroll, dx); + m_font->DrawTextInternal(context, x + scrollInfo.m_textWidth + 1, y + 1, shadowColors, + scrollInfo.m_suffix, alignment, suffixPixelWidth, scroll, dx); } } for (float dx = -offset; dx < maxWidth; dx += scrollInfo.m_totalWidth) { - m_font->DrawTextInternal(context, x + dx, y, renderColors, text, alignment, textPixelWidth, - scroll); - m_font->DrawTextInternal(context, x + dx + scrollInfo.m_textWidth, y, renderColors, - scrollInfo.m_suffix, alignment, suffixPixelWidth, scroll); + m_font->DrawTextInternal(context, x, y, renderColors, text, alignment, textPixelWidth, scroll, + dx); + m_font->DrawTextInternal(context, x + scrollInfo.m_textWidth, y, renderColors, + scrollInfo.m_suffix, alignment, suffixPixelWidth, scroll, dx); } context.RestoreClipRegion(); diff --git a/xbmc/guilib/GUIFontManager.cpp b/xbmc/guilib/GUIFontManager.cpp index 9170cc0406..93f88666a0 100644 --- a/xbmc/guilib/GUIFontManager.cpp +++ b/xbmc/guilib/GUIFontManager.cpp @@ -8,6 +8,7 @@ #include "GUIFontManager.h" +#include "FileItemList.h" #include "GUIComponent.h" #include "GUIFontTTF.h" #include "GUIWindowManager.h" diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp index 50d0e07a44..ff11db14f8 100644 --- a/xbmc/guilib/GUIFontTTF.cpp +++ b/xbmc/guilib/GUIFontTTF.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2024 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -369,7 +369,9 @@ void CGUIFontTTF::DrawTextInternal(CGraphicContext& context, const vecText& text, uint32_t alignment, float maxPixelWidth, - bool scrolling) + bool scrolling, + float dx, + float dy) { if (text.empty()) { @@ -379,15 +381,40 @@ void CGUIFontTTF::DrawTextInternal(CGraphicContext& context, Begin(); uint32_t rawAlignment = alignment; bool dirtyCache(false); + +#if not defined(HAS_DX) + // round coordinates to the pixel grid. otherwise, we might sample at the wrong positions. + if (!scrolling) + x = std::round(x); + y = std::round(y); +#else + x += dx; + y += dy; +#endif + +#if not defined(HAS_DX) + // GL can scissor and shader clip + const bool hardwareClipping = true; +#else + // FIXME: remove static (CPU based) clipping for GLES/DX const bool hardwareClipping = m_renderSystem->ScissorsCanEffectClipping(); +#endif + + // FIXME: remove positional stuff once GLES/DX are brought up to date CGUIFontCacheStaticPosition staticPos(x, y); CGUIFontCacheDynamicPosition dynamicPos; + +#if not defined(HAS_DX) + // dummy positions for the time being + dynamicPos = CGUIFontCacheDynamicPosition(0.0f, 0.0f, 0.0f); +#else if (hardwareClipping) { dynamicPos = CGUIFontCacheDynamicPosition(context.ScaleFinalXCoord(x, y), context.ScaleFinalYCoord(x, y), context.ScaleFinalZCoord(x, y)); } +#endif CVertexBuffer unusedVertexBuffer; CVertexBuffer& vertexBuffer = @@ -425,8 +452,14 @@ void CGUIFontTTF::DrawTextInternal(CGraphicContext& context, const std::vector<Glyph> glyphs = GetHarfBuzzShapedGlyphs(text); // save the origin, which is scaled separately +#if not defined(HAS_DX) + // the origin is now at [0,0], and not at "random" locations anymore. positioning is done in the vertex shader. + m_originX = 0; + m_originY = 0; +#else m_originX = x; m_originY = y; +#endif // cache the ellipses width if (!m_ellipseCached) @@ -677,7 +710,11 @@ void CGUIFontTTF::DrawTextInternal(CGraphicContext& context, scrolling, std::chrono::steady_clock::now(), dirtyCache); CVertexBuffer newVertexBuffer = CreateVertexBuffer(*tempVertices); vertexBuffer = newVertexBuffer; +#if not defined(HAS_DX) + m_vertexTrans.emplace_back(x, y, 0.0f, &vertexBuffer, context.GetClipRegion(), dx, dy); +#else m_vertexTrans.emplace_back(.0f, .0f, .0f, &vertexBuffer, context.GetClipRegion()); +#endif } else { @@ -691,8 +728,12 @@ void CGUIFontTTF::DrawTextInternal(CGraphicContext& context, else { if (hardwareClipping) +#if not defined(HAS_DX) + m_vertexTrans.emplace_back(x, y, 0.0f, &vertexBuffer, context.GetClipRegion(), dx, dy); +#else m_vertexTrans.emplace_back(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertexBuffer, context.GetClipRegion()); +#endif else /* Append the vertices from the cache to the set collected since the first Begin() call */ m_vertex.insert(m_vertex.end(), vertices->begin(), vertices->end()); @@ -1098,12 +1139,19 @@ void CGUIFontTTF::RenderCharacter(CGraphicContext& context, // posX and posY are relative to our origin, and the textcell is offset // from our (posX, posY). Plus, these are unscaled quantities compared to the underlying GUI resolution +#if not defined(HAS_DX) + CRect vertex((posX + ch->m_offsetX), (posY + ch->m_offsetY), (posX + ch->m_offsetX + width), + (posY + ch->m_offsetY + height)); +#else CRect vertex((posX + ch->m_offsetX) * context.GetGUIScaleX(), (posY + ch->m_offsetY) * context.GetGUIScaleY(), (posX + ch->m_offsetX + width) * context.GetGUIScaleX(), (posY + ch->m_offsetY + height) * context.GetGUIScaleY()); vertex += CPoint(m_originX, m_originY); +#endif CRect texture(ch->m_left, ch->m_top, ch->m_right, ch->m_bottom); + +#if defined(HAS_DX) if (!m_renderSystem->ScissorsCanEffectClipping()) context.ClipRect(vertex, texture); @@ -1163,6 +1211,14 @@ void CGUIFontTTF::RenderCharacter(CGraphicContext& context, const float tr = texture.x2 * m_textureScaleX; const float tt = texture.y1 * m_textureScaleY; const float tb = texture.y2 * m_textureScaleY; +#else + // when scaling by shader, we have to grow the vertex and texture coords + // by .5 or we would ommit pixels when animating. + const float tl = (texture.x1 - .5f) * m_textureScaleX; + const float tr = (texture.x2 + .5f) * m_textureScaleX; + const float tt = (texture.y1 - .5f) * m_textureScaleY; + const float tb = (texture.y2 + .5f) * m_textureScaleY; +#endif vertices.resize(vertices.size() + VERTEX_PER_GLYPH); SVertex* v = &vertices[vertices.size() - VERTEX_PER_GLYPH]; @@ -1208,29 +1264,38 @@ void CGUIFontTTF::RenderCharacter(CGraphicContext& context, v[3].v = tb; #else // GL / GLES uses triangle strips, not quads, so have to rearrange the vertex order + // GL uses vertex shaders to manipulate text rotation/translation/scaling/clipping. + + // nudge position to align with raster grid. messes up kerning, but also avoids + // linear filtering (when not scaled/rotated). + float xOffset = 0.0f; + if (roundX) + xOffset = (vertex.x1 - std::floor(vertex.x1)); + float yOffset = (vertex.y1 - std::floor(vertex.y1)); + v[0].u = tl; v[0].v = tt; - v[0].x = x[0]; - v[0].y = y[0]; - v[0].z = z[0]; + v[0].x = vertex.x1 - xOffset - 0.5f; + v[0].y = vertex.y1 - yOffset - 0.5f; + v[0].z = 0; v[1].u = tl; v[1].v = tb; - v[1].x = x[3]; - v[1].y = y[3]; - v[1].z = z[3]; + v[1].x = vertex.x1 - xOffset - 0.5f; + v[1].y = vertex.y2 - yOffset + 0.5f; + v[1].z = 0; v[2].u = tr; v[2].v = tt; - v[2].x = x[1]; - v[2].y = y[1]; - v[2].z = z[1]; + v[2].x = vertex.x2 - xOffset + 0.5f; + v[2].y = vertex.y1 - yOffset - 0.5f; + v[2].z = 0; v[3].u = tr; v[3].v = tb; - v[3].x = x[2]; - v[3].y = y[2]; - v[3].z = z[2]; + v[3].x = vertex.x2 - xOffset + 0.5f; + v[3].y = vertex.y2 - yOffset + 0.5f; + v[3].z = 0; #endif } diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h index 2ed270343d..02a0ac16df 100644 --- a/xbmc/guilib/GUIFontTTF.h +++ b/xbmc/guilib/GUIFontTTF.h @@ -164,7 +164,9 @@ protected: const vecText& text, uint32_t alignment, float maxPixelWidth, - bool scrolling); + bool scrolling, + float dx = 0.0f, + float dy = 0.0f); float m_height{0.0f}; @@ -238,16 +240,22 @@ protected: float m_translateX; float m_translateY; float m_translateZ; + float m_offsetX; // skews the "raw" mesh before applying UI matrix (useful for scrolling) + float m_offsetY; const CVertexBuffer* m_vertexBuffer; CRect m_clip; CTranslatedVertices(float translateX, float translateY, float translateZ, const CVertexBuffer* vertexBuffer, - const CRect& clip) + const CRect& clip, + float offsetX = 0.0f, + float offsetY = 0.0f) : m_translateX(translateX), m_translateY(translateY), m_translateZ(translateZ), + m_offsetX(offsetX), + m_offsetY(offsetY), m_vertexBuffer(vertexBuffer), m_clip(clip) { diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp index 529078811e..3706883911 100644 --- a/xbmc/guilib/GUIFontTTFGL.cpp +++ b/xbmc/guilib/GUIFontTTFGL.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2024 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -65,7 +65,18 @@ bool CGUIFontTTFGL::FirstBegin() internalFormat = GL_R8; else internalFormat = GL_LUMINANCE; + renderSystem->EnableShader(ShaderMethodGL::SM_FONTS); + if (renderSystem->ScissorsCanEffectClipping()) + { + m_scissorClip = true; + } + else + { + m_scissorClip = false; + renderSystem->ResetScissors(); + renderSystem->EnableShader(ShaderMethodGL::SM_FONTS_SHADER_CLIP); + } if (m_textureStatus == TEXTURE_REALLOCATED) { @@ -129,6 +140,9 @@ bool CGUIFontTTFGL::FirstBegin() void CGUIFontTTFGL::LastEnd() { + // static vertex arrays are not supported anymore + assert(m_vertex.empty()); + CWinSystemBase* const winSystem = CServiceBroker::GetWinSystem(); if (!winSystem) return; @@ -138,7 +152,9 @@ void CGUIFontTTFGL::LastEnd() GLint posLoc = renderSystem->ShaderGetPos(); GLint colLoc = renderSystem->ShaderGetCol(); GLint tex0Loc = renderSystem->ShaderGetCoord0(); - GLint modelLoc = renderSystem->ShaderGetModel(); + GLint clipUniformLoc = renderSystem->ShaderGetClip(); + GLint coordStepUniformLoc = renderSystem->ShaderGetCoordStep(); + GLint matrixUniformLoc = renderSystem->ShaderGetMatrix(); CreateStaticVertexBuffers(); @@ -147,44 +163,6 @@ void CGUIFontTTFGL::LastEnd() glEnableVertexAttribArray(colLoc); glEnableVertexAttribArray(tex0Loc); - if (!m_vertex.empty()) - { - - // Deal with vertices that had to use software clipping - std::vector<SVertex> vecVertices(6 * (m_vertex.size() / 4)); - SVertex* vertices = &vecVertices[0]; - for (size_t i = 0; i < m_vertex.size(); i += 4) - { - *vertices++ = m_vertex[i]; - *vertices++ = m_vertex[i + 1]; - *vertices++ = m_vertex[i + 2]; - - *vertices++ = m_vertex[i + 1]; - *vertices++ = m_vertex[i + 3]; - *vertices++ = m_vertex[i + 2]; - } - vertices = &vecVertices[0]; - - GLuint VertexVBO; - - glGenBuffers(1, &VertexVBO); - glBindBuffer(GL_ARRAY_BUFFER, VertexVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(SVertex) * vecVertices.size(), &vecVertices[0], - GL_STATIC_DRAW); - - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), - reinterpret_cast<const GLvoid*>(offsetof(SVertex, x))); - glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), - reinterpret_cast<const GLvoid*>(offsetof(SVertex, r))); - glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), - reinterpret_cast<const GLvoid*>(offsetof(SVertex, u))); - - glDrawArrays(GL_TRIANGLES, 0, vecVertices.size()); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glDeleteBuffers(1, &VertexVBO); - } - if (!m_vertexTrans.empty()) { // Deal with the vertices that can be hardware clipped and therefore translated @@ -211,14 +189,55 @@ void CGUIFontTTFGL::LastEnd() // skip empty clip if (clip.IsEmpty()) continue; + } + + if (m_scissorClip) + { + // clip using scissors renderSystem->SetScissors(clip); } + else + { + // clip using vertex shader + renderSystem->ResetScissors(); + + float x1 = + m_vertexTrans[i].m_clip.x1 - m_vertexTrans[i].m_translateX - m_vertexTrans[i].m_offsetX; + float y1 = + m_vertexTrans[i].m_clip.y1 - m_vertexTrans[i].m_translateY - m_vertexTrans[i].m_offsetY; + float x2 = + m_vertexTrans[i].m_clip.x2 - m_vertexTrans[i].m_translateX - m_vertexTrans[i].m_offsetX; + float y2 = + m_vertexTrans[i].m_clip.y2 - m_vertexTrans[i].m_translateY - m_vertexTrans[i].m_offsetY; + + glUniform4f(clipUniformLoc, x1, y1, x2, y2); + + // setup texture step + float stepX = context.GetGUIScaleX() / (static_cast<float>(m_textureWidth)); + float stepY = context.GetGUIScaleY() / (static_cast<float>(m_textureHeight)); + glUniform4f(coordStepUniformLoc, stepX, stepY, 1.0f, 1.0f); + } - // Apply the translation to the currently active (top-of-stack) model view matrix - glMatrixModview.Push(); - glMatrixModview.Get().Translatef(m_vertexTrans[i].m_translateX, m_vertexTrans[i].m_translateY, - m_vertexTrans[i].m_translateZ); - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glMatrixModview.Get()); + // calculate the fractional offset to the ideal position + float fractX = + context.ScaleFinalXCoord(m_vertexTrans[i].m_translateX, m_vertexTrans[i].m_translateY); + float fractY = + context.ScaleFinalYCoord(m_vertexTrans[i].m_translateX, m_vertexTrans[i].m_translateY); + fractX = -fractX + std::round(fractX); + fractY = -fractY + std::round(fractY); + + // proj * model * gui * scroll * translation * scaling * correction factor + CMatrixGL matrix = glMatrixProject.Get(); + matrix.MultMatrixf(glMatrixModview.Get()); + matrix.MultMatrixf(CMatrixGL(context.GetGUIMatrix())); + matrix.Translatef(m_vertexTrans[i].m_offsetX, m_vertexTrans[i].m_offsetY, 0.0f); + matrix.Translatef(m_vertexTrans[i].m_translateX, m_vertexTrans[i].m_translateY, 0.0f); + // the gui matrix messes with the scale. correct it here for now. + matrix.Scalef(context.GetGUIScaleX(), context.GetGUIScaleY(), 1.0f); + // the gui matrix doesn't align to exact pixel coords atm. correct it here for now. + matrix.Translatef(fractX, fractY, 0.0f); + + glUniformMatrix4fv(matrixUniformLoc, 1, GL_FALSE, matrix); // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point glBindBuffer(GL_ARRAY_BUFFER, m_vertexTrans[i].m_vertexBuffer->bufferHandle); @@ -245,13 +264,12 @@ void CGUIFontTTFGL::LastEnd() glDrawElements(GL_TRIANGLES, 6 * count, GL_UNSIGNED_SHORT, 0); } - - glMatrixModview.Pop(); } + // Restore the original scissor rectangle - renderSystem->SetScissors(scissor); - // Restore the original model view matrix - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glMatrixModview.Get()); + if (m_scissorClip) + renderSystem->SetScissors(scissor); + // Unbind GL_ARRAY_BUFFER and GL_ELEMENT_ARRAY_BUFFER glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/xbmc/guilib/GUIFontTTFGL.h b/xbmc/guilib/GUIFontTTFGL.h index 22fbe6419b..e59a54a23c 100644 --- a/xbmc/guilib/GUIFontTTFGL.h +++ b/xbmc/guilib/GUIFontTTFGL.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2024 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -55,4 +55,6 @@ private: TextureStatus m_textureStatus{TEXTURE_VOID}; static bool m_staticVertexBufferCreated; + + bool m_scissorClip{false}; }; diff --git a/xbmc/guilib/GUIFontTTFGLES.cpp b/xbmc/guilib/GUIFontTTFGLES.cpp index c00a601319..67cceae441 100644 --- a/xbmc/guilib/GUIFontTTFGLES.cpp +++ b/xbmc/guilib/GUIFontTTFGLES.cpp @@ -62,6 +62,17 @@ bool CGUIFontTTFGLES::FirstBegin() GLenum pixformat = GL_ALPHA; // deprecated GLenum internalFormat = GL_ALPHA; + if (renderSystem->ScissorsCanEffectClipping()) + { + m_scissorClip = true; + } + else + { + m_scissorClip = false; + renderSystem->ResetScissors(); + renderSystem->EnableGUIShader(ShaderMethodGLES::SM_FONTS_SHADER_CLIP); + } + if (m_textureStatus == TEXTURE_REALLOCATED) { if (glIsTexture(m_nTexture)) @@ -124,6 +135,9 @@ bool CGUIFontTTFGLES::FirstBegin() void CGUIFontTTFGLES::LastEnd() { + // static vertex arrays are not supported anymore + assert(m_vertex.empty()); + CWinSystemBase* const winSystem = CServiceBroker::GetWinSystem(); if (!winSystem) return; @@ -134,7 +148,9 @@ void CGUIFontTTFGLES::LastEnd() GLint posLoc = renderSystem->GUIShaderGetPos(); GLint colLoc = renderSystem->GUIShaderGetCol(); GLint tex0Loc = renderSystem->GUIShaderGetCoord0(); - GLint modelLoc = renderSystem->GUIShaderGetModel(); + GLint clipUniformLoc = renderSystem->GUIShaderGetClip(); + GLint coordStepUniformLoc = renderSystem->GUIShaderGetCoordStep(); + GLint matrixUniformLoc = renderSystem->GUIShaderGetMatrix(); CreateStaticVertexBuffers(); @@ -143,35 +159,6 @@ void CGUIFontTTFGLES::LastEnd() glEnableVertexAttribArray(colLoc); glEnableVertexAttribArray(tex0Loc); - if (!m_vertex.empty()) - { - // Deal with vertices that had to use software clipping - std::vector<SVertex> vecVertices(6 * (m_vertex.size() / 4)); - SVertex* vertices = &vecVertices[0]; - - for (size_t i = 0; i < m_vertex.size(); i += 4) - { - *vertices++ = m_vertex[i]; - *vertices++ = m_vertex[i + 1]; - *vertices++ = m_vertex[i + 2]; - - *vertices++ = m_vertex[i + 1]; - *vertices++ = m_vertex[i + 3]; - *vertices++ = m_vertex[i + 2]; - } - - vertices = &vecVertices[0]; - - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), - reinterpret_cast<char*>(vertices) + offsetof(SVertex, x)); - glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), - reinterpret_cast<char*>(vertices) + offsetof(SVertex, r)); - glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), - reinterpret_cast<char*>(vertices) + offsetof(SVertex, u)); - - glDrawArrays(GL_TRIANGLES, 0, vecVertices.size()); - } - if (!m_vertexTrans.empty()) { // Deal with the vertices that can be hardware clipped and therefore translated @@ -198,14 +185,54 @@ void CGUIFontTTFGLES::LastEnd() // skip empty clip if (clip.IsEmpty()) continue; + } + if (m_scissorClip) + { + // clip using scissors renderSystem->SetScissors(clip); } + else + { + // clip using vertex shader + renderSystem->ResetScissors(); + + float x1 = + m_vertexTrans[i].m_clip.x1 - m_vertexTrans[i].m_translateX - m_vertexTrans[i].m_offsetX; + float y1 = + m_vertexTrans[i].m_clip.y1 - m_vertexTrans[i].m_translateY - m_vertexTrans[i].m_offsetY; + float x2 = + m_vertexTrans[i].m_clip.x2 - m_vertexTrans[i].m_translateX - m_vertexTrans[i].m_offsetX; + float y2 = + m_vertexTrans[i].m_clip.y2 - m_vertexTrans[i].m_translateY - m_vertexTrans[i].m_offsetY; + + glUniform4f(clipUniformLoc, x1, y1, x2, y2); + + // setup texture step + float stepX = context.GetGUIScaleX() / (static_cast<float>(m_textureWidth)); + float stepY = context.GetGUIScaleY() / (static_cast<float>(m_textureHeight)); + glUniform4f(coordStepUniformLoc, stepX, stepY, 1.0f, 1.0f); + } - // Apply the translation to the currently active (top-of-stack) model view matrix - glMatrixModview.Push(); - glMatrixModview.Get().Translatef(m_vertexTrans[i].m_translateX, m_vertexTrans[i].m_translateY, - m_vertexTrans[i].m_translateZ); - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glMatrixModview.Get()); + // calculate the fractional offset to the ideal position + float fractX = + context.ScaleFinalXCoord(m_vertexTrans[i].m_translateX, m_vertexTrans[i].m_translateY); + float fractY = + context.ScaleFinalYCoord(m_vertexTrans[i].m_translateX, m_vertexTrans[i].m_translateY); + fractX = -fractX + std::round(fractX); + fractY = -fractY + std::round(fractY); + + // proj * model * gui * scroll * translation * scaling * correction factor + CMatrixGL matrix = glMatrixProject.Get(); + matrix.MultMatrixf(glMatrixModview.Get()); + matrix.MultMatrixf(CMatrixGL(context.GetGUIMatrix())); + matrix.Translatef(m_vertexTrans[i].m_offsetX, m_vertexTrans[i].m_offsetY, 0.0f); + matrix.Translatef(m_vertexTrans[i].m_translateX, m_vertexTrans[i].m_translateY, 0.0f); + // the gui matrix messes with the scale. correct it here for now. + matrix.Scalef(context.GetGUIScaleX(), context.GetGUIScaleY(), 1.0f); + // the gui matrix doesn't align to exact pixel coords atm. correct it here for now. + matrix.Translatef(fractX, fractY, 0.0f); + + glUniformMatrix4fv(matrixUniformLoc, 1, GL_FALSE, matrix); // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point glBindBuffer(GL_ARRAY_BUFFER, m_vertexTrans[i].m_vertexBuffer->bufferHandle); @@ -236,9 +263,8 @@ void CGUIFontTTFGLES::LastEnd() glMatrixModview.Pop(); } // Restore the original scissor rectangle - renderSystem->SetScissors(scissor); - // Restore the original model view matrix - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glMatrixModview.Get()); + if (m_scissorClip) + renderSystem->SetScissors(scissor); // Unbind GL_ARRAY_BUFFER and GL_ELEMENT_ARRAY_BUFFER glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/xbmc/guilib/GUIFontTTFGLES.h b/xbmc/guilib/GUIFontTTFGLES.h index ae03da74e6..264d1a7611 100644 --- a/xbmc/guilib/GUIFontTTFGLES.h +++ b/xbmc/guilib/GUIFontTTFGLES.h @@ -55,4 +55,5 @@ private: TextureStatus m_textureStatus{TEXTURE_VOID}; static bool m_staticVertexBufferCreated; + bool m_scissorClip{false}; }; diff --git a/xbmc/guilib/GUIMultiImage.cpp b/xbmc/guilib/GUIMultiImage.cpp index e42dc8b1b3..efc5c18b4b 100644 --- a/xbmc/guilib/GUIMultiImage.cpp +++ b/xbmc/guilib/GUIMultiImage.cpp @@ -9,6 +9,7 @@ #include "GUIMultiImage.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIMessage.h" #include "ServiceBroker.h" #include "TextureCache.h" diff --git a/xbmc/guilib/guiinfo/LibraryGUIInfo.cpp b/xbmc/guilib/guiinfo/LibraryGUIInfo.cpp index f7aceadb7f..0ffcafee4b 100644 --- a/xbmc/guilib/guiinfo/LibraryGUIInfo.cpp +++ b/xbmc/guilib/guiinfo/LibraryGUIInfo.cpp @@ -9,6 +9,7 @@ #include "guilib/guiinfo/LibraryGUIInfo.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "filesystem/Directory.h" diff --git a/xbmc/guilib/guiinfo/SystemGUIInfo.cpp b/xbmc/guilib/guiinfo/SystemGUIInfo.cpp index fceb56bb7b..da1d7dc97b 100644 --- a/xbmc/guilib/guiinfo/SystemGUIInfo.cpp +++ b/xbmc/guilib/guiinfo/SystemGUIInfo.cpp @@ -9,6 +9,7 @@ #include "guilib/guiinfo/SystemGUIInfo.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "LangInfo.h" #include "ServiceBroker.h" diff --git a/xbmc/guilib/guiinfo/VideoGUIInfo.cpp b/xbmc/guilib/guiinfo/VideoGUIInfo.cpp index b4e61a3078..9e440b2539 100644 --- a/xbmc/guilib/guiinfo/VideoGUIInfo.cpp +++ b/xbmc/guilib/guiinfo/VideoGUIInfo.cpp @@ -481,7 +481,7 @@ bool CVideoGUIInfo::GetLabel(std::string& value, const CFileItem *item, int cont return true; case LISTITEM_FILENAME: case LISTITEM_FILE_EXTENSION: - if (item->IsVideoDb()) + if (VIDEO::IsVideoDb(*item)) value = URIUtils::GetFileName(tag->m_strFileNameAndPath); else if (item->HasMusicInfoTag()) // special handling for music videos, which have both a videotag and a musictag break; @@ -496,7 +496,7 @@ bool CVideoGUIInfo::GetLabel(std::string& value, const CFileItem *item, int cont return true; case LISTITEM_FOLDERNAME: case LISTITEM_PATH: - if (item->IsVideoDb()) + if (VIDEO::IsVideoDb(*item)) { if (item->m_bIsFolder) value = tag->m_strPath; @@ -517,7 +517,7 @@ bool CVideoGUIInfo::GetLabel(std::string& value, const CFileItem *item, int cont } return true; case LISTITEM_FILENAME_AND_PATH: - if (item->IsVideoDb()) + if (VIDEO::IsVideoDb(*item)) value = tag->m_strFileNameAndPath; else if (item->HasMusicInfoTag()) // special handling for music videos, which have both a videotag and a musictag break; diff --git a/xbmc/input/keyboard/KeyboardLayoutManager.cpp b/xbmc/input/keyboard/KeyboardLayoutManager.cpp index 4727a633ed..98ba2c5020 100644 --- a/xbmc/input/keyboard/KeyboardLayoutManager.cpp +++ b/xbmc/input/keyboard/KeyboardLayoutManager.cpp @@ -9,6 +9,7 @@ #include "KeyboardLayoutManager.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "filesystem/Directory.h" diff --git a/xbmc/input/keymaps/ButtonTranslator.cpp b/xbmc/input/keymaps/ButtonTranslator.cpp index a7d3e50e57..34aa0164bd 100644 --- a/xbmc/input/keymaps/ButtonTranslator.cpp +++ b/xbmc/input/keymaps/ButtonTranslator.cpp @@ -10,6 +10,7 @@ #include "AppTranslator.h" #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/Directory.h" #include "guilib/WindowIDs.h" #include "input/WindowTranslator.h" diff --git a/xbmc/interfaces/builtins/PlayerBuiltins.cpp b/xbmc/interfaces/builtins/PlayerBuiltins.cpp index 10897723d9..2173959123 100644 --- a/xbmc/interfaces/builtins/PlayerBuiltins.cpp +++ b/xbmc/interfaces/builtins/PlayerBuiltins.cpp @@ -9,6 +9,7 @@ #include "PlayerBuiltins.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "PartyModeManager.h" #include "PlayListPlayer.h" diff --git a/xbmc/interfaces/json-rpc/AddonsOperations.cpp b/xbmc/interfaces/json-rpc/AddonsOperations.cpp index db6c90a191..3daac8cc0b 100644 --- a/xbmc/interfaces/json-rpc/AddonsOperations.cpp +++ b/xbmc/interfaces/json-rpc/AddonsOperations.cpp @@ -11,7 +11,6 @@ #include "JSONUtils.h" #include "ServiceBroker.h" #include "TextureCache.h" -#include "addons/AddonDatabase.h" #include "addons/AddonManager.h" #include "addons/PluginSource.h" #include "addons/addoninfo/AddonInfo.h" @@ -122,9 +121,8 @@ JSONRPC_STATUS CAddonsOperations::GetAddons(const std::string &method, ITranspor int start, end; HandleLimits(parameterObject, result, addons.size(), start, end); - CAddonDatabase addondb; for (int index = start; index < end; index++) - FillDetails(addons.at(index), parameterObject["properties"], result["addons"], addondb, true); + FillDetails(addons.at(index), parameterObject["properties"], result["addons"], true); return OK; } @@ -138,8 +136,7 @@ JSONRPC_STATUS CAddonsOperations::GetAddonDetails(const std::string &method, ITr addon->Type() >= AddonType::MAX_TYPES) return InvalidParams; - CAddonDatabase addondb; - FillDetails(addon, parameterObject["properties"], result["addon"], addondb); + FillDetails(addon, parameterObject["properties"], result["addon"], false); return OK; } @@ -272,8 +269,7 @@ static CVariant Serialize(const AddonPtr& addon) void CAddonsOperations::FillDetails(const std::shared_ptr<ADDON::IAddon>& addon, const CVariant& fields, CVariant& result, - CAddonDatabase& addondb, - bool append /* = false */) + bool append) { if (addon.get() == NULL) return; diff --git a/xbmc/interfaces/json-rpc/AddonsOperations.h b/xbmc/interfaces/json-rpc/AddonsOperations.h index 727f418999..cf78a2dba0 100644 --- a/xbmc/interfaces/json-rpc/AddonsOperations.h +++ b/xbmc/interfaces/json-rpc/AddonsOperations.h @@ -35,7 +35,6 @@ namespace JSONRPC static void FillDetails(const std::shared_ptr<ADDON::IAddon>& addon, const CVariant& fields, CVariant& result, - ADDON::CAddonDatabase& addondb, - bool append = false); + bool append); }; } diff --git a/xbmc/interfaces/json-rpc/AudioLibrary.cpp b/xbmc/interfaces/json-rpc/AudioLibrary.cpp index 3d6fa79d79..951cd7ae8d 100644 --- a/xbmc/interfaces/json-rpc/AudioLibrary.cpp +++ b/xbmc/interfaces/json-rpc/AudioLibrary.cpp @@ -9,6 +9,7 @@ #include "AudioLibrary.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "TextureDatabase.h" #include "Util.h" diff --git a/xbmc/interfaces/json-rpc/FileItemHandler.cpp b/xbmc/interfaces/json-rpc/FileItemHandler.cpp index 07426447e1..7a524fd337 100644 --- a/xbmc/interfaces/json-rpc/FileItemHandler.cpp +++ b/xbmc/interfaces/json-rpc/FileItemHandler.cpp @@ -9,6 +9,7 @@ #include "FileItemHandler.h" #include "AudioLibrary.h" +#include "FileItemList.h" #include "FileOperations.h" #include "ServiceBroker.h" #include "TextureDatabase.h" diff --git a/xbmc/interfaces/json-rpc/FileOperations.cpp b/xbmc/interfaces/json-rpc/FileOperations.cpp index 4658e99353..a495607ff9 100644 --- a/xbmc/interfaces/json-rpc/FileOperations.cpp +++ b/xbmc/interfaces/json-rpc/FileOperations.cpp @@ -10,6 +10,7 @@ #include "AudioLibrary.h" #include "FileItem.h" +#include "FileItemList.h" #include "MediaSource.h" #include "ServiceBroker.h" #include "URL.h" diff --git a/xbmc/interfaces/json-rpc/PVROperations.cpp b/xbmc/interfaces/json-rpc/PVROperations.cpp index 0ec809481c..07c8d93222 100644 --- a/xbmc/interfaces/json-rpc/PVROperations.cpp +++ b/xbmc/interfaces/json-rpc/PVROperations.cpp @@ -9,6 +9,7 @@ #include "PVROperations.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "pvr/PVRManager.h" #include "pvr/PVRPlaybackState.h" diff --git a/xbmc/interfaces/json-rpc/PlayerOperations.cpp b/xbmc/interfaces/json-rpc/PlayerOperations.cpp index 5029549541..02747f18fb 100644 --- a/xbmc/interfaces/json-rpc/PlayerOperations.cpp +++ b/xbmc/interfaces/json-rpc/PlayerOperations.cpp @@ -10,6 +10,7 @@ #include "AudioLibrary.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "GUIUserMessages.h" #include "PartyModeManager.h" diff --git a/xbmc/interfaces/json-rpc/PlaylistOperations.cpp b/xbmc/interfaces/json-rpc/PlaylistOperations.cpp index 61e04ac711..49955bc68f 100644 --- a/xbmc/interfaces/json-rpc/PlaylistOperations.cpp +++ b/xbmc/interfaces/json-rpc/PlaylistOperations.cpp @@ -9,6 +9,7 @@ #include "PlaylistOperations.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "PlayListPlayer.h" #include "ServiceBroker.h" diff --git a/xbmc/interfaces/json-rpc/ProfilesOperations.cpp b/xbmc/interfaces/json-rpc/ProfilesOperations.cpp index adfb010430..17facb7b0e 100644 --- a/xbmc/interfaces/json-rpc/ProfilesOperations.cpp +++ b/xbmc/interfaces/json-rpc/ProfilesOperations.cpp @@ -9,6 +9,7 @@ #include "ProfilesOperations.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "ServiceBroker.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/interfaces/json-rpc/TextureOperations.cpp b/xbmc/interfaces/json-rpc/TextureOperations.cpp index d6ffcc8761..d6915314bf 100644 --- a/xbmc/interfaces/json-rpc/TextureOperations.cpp +++ b/xbmc/interfaces/json-rpc/TextureOperations.cpp @@ -9,6 +9,7 @@ #include "TextureOperations.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "TextureCache.h" #include "TextureDatabase.h" diff --git a/xbmc/interfaces/json-rpc/VideoLibrary.cpp b/xbmc/interfaces/json-rpc/VideoLibrary.cpp index 0f7499ec0e..cb69a5f002 100644 --- a/xbmc/interfaces/json-rpc/VideoLibrary.cpp +++ b/xbmc/interfaces/json-rpc/VideoLibrary.cpp @@ -9,6 +9,7 @@ #include "VideoLibrary.h" #include "FileItem.h" +#include "FileItemList.h" #include "PVROperations.h" #include "ServiceBroker.h" #include "TextureDatabase.h" diff --git a/xbmc/interfaces/legacy/Control.cpp b/xbmc/interfaces/legacy/Control.cpp index 2ad9c2197e..d75778b5f5 100644 --- a/xbmc/interfaces/legacy/Control.cpp +++ b/xbmc/interfaces/legacy/Control.cpp @@ -9,6 +9,7 @@ #include "Control.h" #include "AddonUtils.h" +#include "FileItemList.h" #include "LanguageHook.h" #include "ServiceBroker.h" #include "WindowException.h" diff --git a/xbmc/interfaces/legacy/Dialog.cpp b/xbmc/interfaces/legacy/Dialog.cpp index 55812f9099..9674875ea1 100644 --- a/xbmc/interfaces/legacy/Dialog.cpp +++ b/xbmc/interfaces/legacy/Dialog.cpp @@ -7,6 +7,7 @@ */ #include "Dialog.h" +#include "FileItemList.h" #include "LanguageHook.h" #include "ListItem.h" #include "ModuleXbmcgui.h" diff --git a/xbmc/interfaces/legacy/ModuleXbmcplugin.cpp b/xbmc/interfaces/legacy/ModuleXbmcplugin.cpp index 0af97b71ac..bc399cc1c9 100644 --- a/xbmc/interfaces/legacy/ModuleXbmcplugin.cpp +++ b/xbmc/interfaces/legacy/ModuleXbmcplugin.cpp @@ -9,6 +9,7 @@ #include "ModuleXbmcplugin.h" #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/PluginDirectory.h" namespace XBMCAddon diff --git a/xbmc/interfaces/legacy/ModuleXbmcvfs.cpp b/xbmc/interfaces/legacy/ModuleXbmcvfs.cpp index c6858e3617..0d2391523f 100644 --- a/xbmc/interfaces/legacy/ModuleXbmcvfs.cpp +++ b/xbmc/interfaces/legacy/ModuleXbmcvfs.cpp @@ -9,6 +9,7 @@ #include "ModuleXbmcvfs.h" #include "FileItem.h" +#include "FileItemList.h" #include "LanguageHook.h" #include "URL.h" #include "Util.h" diff --git a/xbmc/interfaces/legacy/PlayList.cpp b/xbmc/interfaces/legacy/PlayList.cpp index d6d19d8866..649bc89892 100644 --- a/xbmc/interfaces/legacy/PlayList.cpp +++ b/xbmc/interfaces/legacy/PlayList.cpp @@ -8,6 +8,7 @@ #include "PlayList.h" +#include "FileItemList.h" #include "PlayListPlayer.h" #include "ServiceBroker.h" #include "playlists/PlayListFactory.h" diff --git a/xbmc/interfaces/legacy/Player.cpp b/xbmc/interfaces/legacy/Player.cpp index 4fc961cd88..b3aff2dfd5 100644 --- a/xbmc/interfaces/legacy/Player.cpp +++ b/xbmc/interfaces/legacy/Player.cpp @@ -9,6 +9,7 @@ #include "Player.h" #include "AddonUtils.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "GUIUserMessages.h" #include "ListItem.h" diff --git a/xbmc/interfaces/legacy/WindowXML.cpp b/xbmc/interfaces/legacy/WindowXML.cpp index 65dc6c47f9..b127496783 100644 --- a/xbmc/interfaces/legacy/WindowXML.cpp +++ b/xbmc/interfaces/legacy/WindowXML.cpp @@ -8,6 +8,7 @@ #include "WindowXML.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "WindowException.h" #include "WindowInterceptor.h" diff --git a/xbmc/music/ContextMenus.cpp b/xbmc/music/ContextMenus.cpp index 9d146083bc..22df28acd2 100644 --- a/xbmc/music/ContextMenus.cpp +++ b/xbmc/music/ContextMenus.cpp @@ -19,10 +19,12 @@ #include "playlists/PlayListTypes.h" #include "tags/MusicInfoTag.h" #include "utils/Variant.h" +#include "video/VideoFileItemClassify.h" #include <utility> using namespace CONTEXTMENU; +using namespace KODI; CMusicInfo::CMusicInfo(MediaType mediaType) : CStaticContextMenuAction(19033), m_mediaType(std::move(mediaType)) @@ -32,8 +34,10 @@ CMusicInfo::CMusicInfo(MediaType mediaType) bool CMusicInfo::IsVisible(const CFileItem& item) const { return (item.HasMusicInfoTag() && item.GetMusicInfoTag()->GetType() == m_mediaType) || - (m_mediaType == MediaTypeArtist && item.IsVideoDb() && item.HasProperty("artist_musicid")) || - (m_mediaType == MediaTypeAlbum && item.IsVideoDb() && item.HasProperty("album_musicid")); + (m_mediaType == MediaTypeArtist && VIDEO::IsVideoDb(item) && + item.HasProperty("artist_musicid")) || + (m_mediaType == MediaTypeAlbum && VIDEO::IsVideoDb(item) && + item.HasProperty("album_musicid")); } bool CMusicInfo::Execute(const std::shared_ptr<CFileItem>& item) const diff --git a/xbmc/music/GUIViewStateMusic.cpp b/xbmc/music/GUIViewStateMusic.cpp index f14f5015e4..a34d9170a2 100644 --- a/xbmc/music/GUIViewStateMusic.cpp +++ b/xbmc/music/GUIViewStateMusic.cpp @@ -9,6 +9,7 @@ #include "GUIViewStateMusic.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "filesystem/Directory.h" #include "filesystem/MusicDatabaseDirectory.h" @@ -23,8 +24,10 @@ #include "utils/FileExtensionProvider.h" #include "utils/SortUtils.h" #include "utils/log.h" +#include "video/VideoFileItemClassify.h" #include "view/ViewStateSettings.h" +using namespace KODI; using namespace XFILE; using namespace MUSICDATABASEDIRECTORY; @@ -503,7 +506,8 @@ CGUIViewStateWindowMusicNav::CGUIViewStateWindowMusicNav(const CFileItemList& it } else { - if (items.IsVideoDb() && items.Size() > (settings->GetBool(CSettings::SETTING_FILELISTS_SHOWPARENTDIRITEMS)?1:0)) + if (VIDEO::IsVideoDb(items) && + items.Size() > (settings->GetBool(CSettings::SETTING_FILELISTS_SHOWPARENTDIRITEMS) ? 1 : 0)) { XFILE::VIDEODATABASEDIRECTORY::CQueryParams params; XFILE::CVideoDatabaseDirectory::GetQueryParams(items[settings->GetBool(CSettings::SETTING_FILELISTS_SHOWPARENTDIRITEMS) ? 1 : 0]->GetPath(), params); diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp index b5ba07ef8a..a98db00388 100644 --- a/xbmc/music/MusicDatabase.cpp +++ b/xbmc/music/MusicDatabase.cpp @@ -11,6 +11,7 @@ #include "Album.h" #include "Artist.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "LangInfo.h" #include "ServiceBroker.h" diff --git a/xbmc/music/MusicInfoLoader.cpp b/xbmc/music/MusicInfoLoader.cpp index 7cfa0352ff..3ecaa4a417 100644 --- a/xbmc/music/MusicInfoLoader.cpp +++ b/xbmc/music/MusicInfoLoader.cpp @@ -11,6 +11,7 @@ #include "Album.h" #include "Artist.h" #include "FileItem.h" +#include "FileItemList.h" #include "MusicDatabase.h" #include "MusicThumbLoader.h" #include "ServiceBroker.h" diff --git a/xbmc/music/MusicUtils.cpp b/xbmc/music/MusicUtils.cpp index 1f0c60fb70..1984cbb2e8 100644 --- a/xbmc/music/MusicUtils.cpp +++ b/xbmc/music/MusicUtils.cpp @@ -9,6 +9,7 @@ #include "MusicUtils.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "PartyModeManager.h" #include "PlayListPlayer.h" @@ -875,7 +876,7 @@ bool IsItemPlayable(const CFileItem& item) return false; // Exclude all video library items - if (item.IsVideoDb() || StringUtils::StartsWithNoCase(item.GetPath(), "library://video/")) + if (IsVideoDb(item) || StringUtils::StartsWithNoCase(item.GetPath(), "library://video/")) return false; // Exclude other components diff --git a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp index d1559f77fd..fab40e850f 100644 --- a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp +++ b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp @@ -9,6 +9,7 @@ #include "GUIDialogMusicInfo.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" diff --git a/xbmc/music/dialogs/GUIDialogSongInfo.h b/xbmc/music/dialogs/GUIDialogSongInfo.h index 274f1acc0f..7aba18a52a 100644 --- a/xbmc/music/dialogs/GUIDialogSongInfo.h +++ b/xbmc/music/dialogs/GUIDialogSongInfo.h @@ -9,6 +9,7 @@ #pragma once #include "FileItem.h" +#include "FileItemList.h" #include "guilib/GUIDialog.h" #include "threads/Event.h" diff --git a/xbmc/music/infoscanner/MusicInfoScanner.cpp b/xbmc/music/infoscanner/MusicInfoScanner.cpp index f828b44914..3236470c78 100644 --- a/xbmc/music/infoscanner/MusicInfoScanner.cpp +++ b/xbmc/music/infoscanner/MusicInfoScanner.cpp @@ -9,6 +9,7 @@ #include "MusicInfoScanner.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "GUIUserMessages.h" #include "MusicAlbumInfo.h" diff --git a/xbmc/music/windows/GUIWindowMusicBase.cpp b/xbmc/music/windows/GUIWindowMusicBase.cpp index 0754c37e56..b6ced56366 100644 --- a/xbmc/music/windows/GUIWindowMusicBase.cpp +++ b/xbmc/music/windows/GUIWindowMusicBase.cpp @@ -10,6 +10,7 @@ #include "Autorun.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "GUIPassword.h" #include "GUIUserMessages.h" @@ -299,7 +300,7 @@ void CGUIWindowMusicBase::OnItemInfo(int iItem) CFileItemPtr item = m_vecItems->Get(iItem); // Match visibility test of CMusicInfo::IsVisible - if (item->IsVideoDb() && item->HasVideoInfoTag() && + if (IsVideoDb(*item) && item->HasVideoInfoTag() && (item->HasProperty("artist_musicid") || item->HasProperty("album_musicid"))) { // Music video artist or album (navigation by music > music video > artist)) @@ -731,7 +732,7 @@ bool CGUIWindowMusicBase::OnPlayMedia(int iItem, const std::string &player) void CGUIWindowMusicBase::OnRetrieveMusicInfo(CFileItemList& items) { // No need to attempt to read music file tags for music videos - if (items.IsVideoDb()) + if (IsVideoDb(items)) return; if (items.GetFolderCount()==items.Size() || items.IsMusicDb() || (!CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MUSICFILES_USETAGS) && !items.IsCDDA())) diff --git a/xbmc/music/windows/GUIWindowMusicNav.cpp b/xbmc/music/windows/GUIWindowMusicNav.cpp index a544090204..086cbe607f 100644 --- a/xbmc/music/windows/GUIWindowMusicNav.cpp +++ b/xbmc/music/windows/GUIWindowMusicNav.cpp @@ -9,6 +9,7 @@ #include "GUIWindowMusicNav.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "GUIUserMessages.h" #include "PartyModeManager.h" @@ -45,6 +46,7 @@ #include "utils/Variant.h" #include "utils/log.h" #include "video/VideoDatabase.h" +#include "video/VideoFileItemClassify.h" #include "video/dialogs/GUIDialogVideoInfo.h" #include "video/windows/GUIWindowVideoNav.h" #include "view/GUIViewState.h" @@ -53,6 +55,7 @@ using namespace XFILE; using namespace PLAYLIST; using namespace MUSICDATABASEDIRECTORY; using namespace KODI::MESSAGING; +using namespace KODI::VIDEO; #define CONTROL_BTNVIEWASICONS 2 #define CONTROL_BTNSORTBY 3 @@ -386,7 +389,7 @@ bool CGUIWindowMusicNav::GetDirectory(const std::string &strDirectory, CFileItem } // update our content in the info manager - if (StringUtils::StartsWithNoCase(strDirectory, "videodb://") || items.IsVideoDb()) + if (StringUtils::StartsWithNoCase(strDirectory, "videodb://") || IsVideoDb(items)) { CVideoDatabaseDirectory dir; VIDEODATABASEDIRECTORY::NODE_TYPE node = dir.GetDirectoryChildType(items.GetPath()); @@ -624,8 +627,8 @@ void CGUIWindowMusicNav::GetContextButtons(int itemNumber, CContextButtons &butt if (!item->IsParentFolder() && !dir.IsAllItem(item->GetPath())) { - if (item->m_bIsFolder && !item->IsVideoDb() && - !item->IsPlugin() && !StringUtils::StartsWithNoCase(item->GetPath(), "musicsearch://")) + if (item->m_bIsFolder && !IsVideoDb(*item) && !item->IsPlugin() && + !StringUtils::StartsWithNoCase(item->GetPath(), "musicsearch://")) { if (item->IsAlbum()) // enable query all albums button only in album view @@ -718,7 +721,7 @@ bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) { case CONTEXT_BUTTON_INFO: { - if (!item->IsVideoDb()) + if (!IsVideoDb(*item)) return CGUIWindowMusicBase::OnContextButton(itemNumber,button); // music videos - artists @@ -807,7 +810,7 @@ bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) } case CONTEXT_BUTTON_RENAME: - if (!item->IsVideoDb() && !item->IsReadOnly()) + if (!IsVideoDb(*item) && !item->IsReadOnly()) OnRenameItem(itemNumber); CGUIDialogVideoInfo::UpdateVideoItemTitle(item); @@ -823,7 +826,7 @@ bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) if (gui && gui->ConfirmDelete(item->GetPath())) CFileUtils::DeleteItem(item); } - else if (!item->IsVideoDb()) + else if (!IsVideoDb(*item)) OnDeleteItem(itemNumber); else { diff --git a/xbmc/music/windows/GUIWindowMusicPlaylist.cpp b/xbmc/music/windows/GUIWindowMusicPlaylist.cpp index fe1d72a163..85252b86f9 100644 --- a/xbmc/music/windows/GUIWindowMusicPlaylist.cpp +++ b/xbmc/music/windows/GUIWindowMusicPlaylist.cpp @@ -9,6 +9,7 @@ #include "GUIWindowMusicPlaylist.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "PartyModeManager.h" #include "PlayListPlayer.h" diff --git a/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp b/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp index cf9e73e817..16ecdd0c3c 100644 --- a/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp +++ b/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp @@ -10,6 +10,7 @@ #include "Autorun.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" #include "Util.h" diff --git a/xbmc/music/windows/MusicFileItemListModifier.cpp b/xbmc/music/windows/MusicFileItemListModifier.cpp index fe04aed423..5aef6139f2 100644 --- a/xbmc/music/windows/MusicFileItemListModifier.cpp +++ b/xbmc/music/windows/MusicFileItemListModifier.cpp @@ -9,6 +9,7 @@ #include "MusicFileItemListModifier.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "filesystem/MusicDatabaseDirectory/DirectoryNode.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp index eaa0aa58fd..6b30e11e06 100644 --- a/xbmc/network/AirPlayServer.cpp +++ b/xbmc/network/AirPlayServer.cpp @@ -12,6 +12,7 @@ #include "AirPlayServer.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "application/ApplicationComponents.h" diff --git a/xbmc/network/upnp/UPnPInternal.cpp b/xbmc/network/upnp/UPnPInternal.cpp index c9a3bacd4c..f03cab5e27 100644 --- a/xbmc/network/upnp/UPnPInternal.cpp +++ b/xbmc/network/upnp/UPnPInternal.cpp @@ -205,13 +205,13 @@ NPT_String GetMimeType(const CFileItem& item, const PLT_HttpRequestContext* cont /* fallback to generic mime type if not found */ if (mime.IsEmpty()) { - if (VIDEO::IsVideo(item) || item.IsVideoDb()) + if (VIDEO::IsVideo(item) || VIDEO::IsVideoDb(item)) mime = "video/" + ext; else if (item.IsAudio() || item.IsMusicDb()) mime = "audio/" + ext; else if (item.IsPicture()) mime = "image/" + ext; - else if (item.IsSubtitle()) + else if (VIDEO::IsSubtitle(item)) mime = "text/" + ext; } @@ -530,7 +530,7 @@ PLT_MediaObject* BuildObject(CFileItem& item, PopulateObjectFromTag(*tag, *object, &file_path, &resource, quirks, upnp_service); } } - else if (item.IsVideoDb() || VIDEO::IsVideo(item)) + else if (VIDEO::IsVideoDb(item) || VIDEO::IsVideo(item)) { object->m_ObjectClass.type = "object.item.videoItem"; @@ -674,7 +674,7 @@ PLT_MediaObject* BuildObject(CFileItem& item, break; } } - else if (item.IsVideoDb()) + else if (VIDEO::IsVideoDb(item)) { VIDEODATABASEDIRECTORY::NODE_TYPE node = CVideoDatabaseDirectory::GetDirectoryType(item.GetPath()); diff --git a/xbmc/network/upnp/UPnPPlayer.cpp b/xbmc/network/upnp/UPnPPlayer.cpp index 103581afe2..93ef3a58a9 100644 --- a/xbmc/network/upnp/UPnPPlayer.cpp +++ b/xbmc/network/upnp/UPnPPlayer.cpp @@ -225,7 +225,7 @@ int CUPnPPlayer::PlayFile(const CFileItem& file, NPT_CHECK_POINTER_LABEL_SEVERE(m_delegate, failed); - if (file.IsVideoDb()) + if (VIDEO::IsVideoDb(file)) thumb_loader = NPT_Reference<CThumbLoader>(new CVideoThumbLoader()); else if (item.IsMusicDb()) thumb_loader = NPT_Reference<CThumbLoader>(new CMusicThumbLoader()); @@ -419,7 +419,7 @@ bool CUPnPPlayer::QueueNextFile(const CFileItem& file) NPT_String path(file.GetPath().c_str()); NPT_String tmp; - if (file.IsVideoDb()) + if (VIDEO::IsVideoDb(file)) thumb_loader = NPT_Reference<CThumbLoader>(new CVideoThumbLoader()); else if (item.IsMusicDb()) thumb_loader = NPT_Reference<CThumbLoader>(new CMusicThumbLoader()); diff --git a/xbmc/network/upnp/UPnPRenderer.cpp b/xbmc/network/upnp/UPnPRenderer.cpp index ff63888578..acc25a81a9 100644 --- a/xbmc/network/upnp/UPnPRenderer.cpp +++ b/xbmc/network/upnp/UPnPRenderer.cpp @@ -8,6 +8,7 @@ #include "UPnPRenderer.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp index 3618708a5d..17e9cbebc9 100644 --- a/xbmc/network/upnp/UPnPServer.cpp +++ b/xbmc/network/upnp/UPnPServer.cpp @@ -7,6 +7,7 @@ */ #include "UPnPServer.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" #include "TextureDatabase.h" @@ -38,6 +39,7 @@ #include "utils/Variant.h" #include "utils/log.h" #include "video/VideoDatabase.h" +#include "video/VideoFileItemClassify.h" #include "video/VideoLibraryQueue.h" #include "video/VideoThumbLoader.h" #include "view/GUIViewState.h" @@ -49,6 +51,7 @@ NPT_SET_LOCAL_LOGGER("xbmc.upnp.server") using namespace ANNOUNCEMENT; +using namespace KODI::VIDEO; using namespace XFILE; using KODI::UTILITY::CDigest; @@ -713,7 +716,7 @@ NPT_Result CUPnPServer::OnBrowseMetadata(PLT_ActionReference& action, parent = "sources://video/"; // this can only match video sources } - if (item->IsVideoDb()) + if (IsVideoDb(*item)) { thumb_loader = NPT_Reference<CThumbLoader>(new CVideoThumbLoader()); } @@ -1306,7 +1309,7 @@ NPT_Result CUPnPServer::OnUpdateObject(PLT_ActionReference& action, NPT_CHECK_LABEL(FindServiceById("urn:upnp-org:serviceId:ContentDirectory", service), error); NPT_CHECK_LABEL(service->PauseEventing(), error); - if (updated.IsVideoDb()) + if (IsVideoDb(updated)) { CVideoDatabase db; NPT_CHECK_LABEL(!db.Open(), error); @@ -1408,7 +1411,7 @@ NPT_Result CUPnPServer::OnUpdateObject(PLT_ActionReference& action, if (updatelisting) { updated.SetPath(path); - if (updated.IsVideoDb()) + if (IsVideoDb(updated)) CUtil::DeleteVideoDatabaseDirectoryCache(); else if (updated.IsMusicDb()) CUtil::DeleteMusicDatabaseDirectoryCache(); @@ -1525,7 +1528,7 @@ NPT_Result CUPnPServer::ServeFile(const NPT_HttpRequest& request, void CUPnPServer::DefaultSortItems(CFileItemList& items) { CGUIViewState* viewState = - CGUIViewState::GetViewState(items.IsVideoDb() ? WINDOW_VIDEO_NAV : -1, items); + CGUIViewState::GetViewState(IsVideoDb(items) ? WINDOW_VIDEO_NAV : -1, items); if (viewState) { SortDescription sorting = viewState->GetSortMethod(); diff --git a/xbmc/peripherals/addons/PeripheralAddon.cpp b/xbmc/peripherals/addons/PeripheralAddon.cpp index d55dfb55ce..2b7aca7584 100644 --- a/xbmc/peripherals/addons/PeripheralAddon.cpp +++ b/xbmc/peripherals/addons/PeripheralAddon.cpp @@ -9,6 +9,7 @@ #include "PeripheralAddon.h" #include "FileItem.h" +#include "FileItemList.h" #include "PeripheralAddonTranslator.h" #include "addons/addoninfo/AddonInfo.h" #include "addons/addoninfo/AddonType.h" diff --git a/xbmc/peripherals/bus/PeripheralBus.cpp b/xbmc/peripherals/bus/PeripheralBus.cpp index b59ba1dca3..f33b80181b 100644 --- a/xbmc/peripherals/bus/PeripheralBus.cpp +++ b/xbmc/peripherals/bus/PeripheralBus.cpp @@ -9,6 +9,7 @@ #include "PeripheralBus.h" #include "FileItem.h" +#include "FileItemList.h" #include "guilib/LocalizeStrings.h" #include "peripherals/Peripherals.h" #include "peripherals/devices/Peripheral.h" diff --git a/xbmc/peripherals/dialogs/GUIDialogPeripherals.h b/xbmc/peripherals/dialogs/GUIDialogPeripherals.h index 8a54e01aca..4eedb2e390 100644 --- a/xbmc/peripherals/dialogs/GUIDialogPeripherals.h +++ b/xbmc/peripherals/dialogs/GUIDialogPeripherals.h @@ -9,6 +9,7 @@ #pragma once #include "FileItem.h" +#include "FileItemList.h" #include "dialogs/GUIDialogSelect.h" #include "threads/CriticalSection.h" #include "utils/Observer.h" diff --git a/xbmc/pictures/GUIDialogPictureInfo.cpp b/xbmc/pictures/GUIDialogPictureInfo.cpp index 263b48238f..2a4b8cc665 100644 --- a/xbmc/pictures/GUIDialogPictureInfo.cpp +++ b/xbmc/pictures/GUIDialogPictureInfo.cpp @@ -9,6 +9,7 @@ #include "GUIDialogPictureInfo.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "ServiceBroker.h" #include "guilib/GUIComponent.h" diff --git a/xbmc/pictures/GUIViewStatePictures.cpp b/xbmc/pictures/GUIViewStatePictures.cpp index 47d0cdff7a..5b9ebfd208 100644 --- a/xbmc/pictures/GUIViewStatePictures.cpp +++ b/xbmc/pictures/GUIViewStatePictures.cpp @@ -9,6 +9,7 @@ #include "GUIViewStatePictures.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "filesystem/Directory.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/pictures/GUIWindowPictures.cpp b/xbmc/pictures/GUIWindowPictures.cpp index 2abc2a459a..b7345526fd 100644 --- a/xbmc/pictures/GUIWindowPictures.cpp +++ b/xbmc/pictures/GUIWindowPictures.cpp @@ -10,6 +10,7 @@ #include "Autorun.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIDialogPictureInfo.h" #include "GUIPassword.h" #include "GUIWindowSlideShow.h" diff --git a/xbmc/pictures/GUIWindowSlideShow.cpp b/xbmc/pictures/GUIWindowSlideShow.cpp index 59ddf28061..4a47726dc8 100644 --- a/xbmc/pictures/GUIWindowSlideShow.cpp +++ b/xbmc/pictures/GUIWindowSlideShow.cpp @@ -9,6 +9,7 @@ #include "GUIWindowSlideShow.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIDialogPictureInfo.h" #include "GUIInfoManager.h" #include "GUIUserMessages.h" diff --git a/xbmc/pictures/PictureFolderImageFileLoader.cpp b/xbmc/pictures/PictureFolderImageFileLoader.cpp index 1eb58f21b0..b80749b086 100644 --- a/xbmc/pictures/PictureFolderImageFileLoader.cpp +++ b/xbmc/pictures/PictureFolderImageFileLoader.cpp @@ -9,6 +9,7 @@ #include "PictureFolderImageFileLoader.h" #include "FileItem.h" +#include "FileItemList.h" #include "Picture.h" #include "ServiceBroker.h" #include "TextureCache.h" diff --git a/xbmc/pictures/PictureInfoLoader.cpp b/xbmc/pictures/PictureInfoLoader.cpp index 2a62807055..14a880bcec 100644 --- a/xbmc/pictures/PictureInfoLoader.cpp +++ b/xbmc/pictures/PictureInfoLoader.cpp @@ -9,6 +9,7 @@ #include "PictureInfoLoader.h" #include "FileItem.h" +#include "FileItemList.h" #include "PictureInfoTag.h" #include "ServiceBroker.h" #include "settings/Settings.h" diff --git a/xbmc/pictures/PictureThumbLoader.cpp b/xbmc/pictures/PictureThumbLoader.cpp index 8e1a6bc95d..0745c6e3ca 100644 --- a/xbmc/pictures/PictureThumbLoader.cpp +++ b/xbmc/pictures/PictureThumbLoader.cpp @@ -9,6 +9,7 @@ #include "PictureThumbLoader.h" #include "FileItem.h" +#include "FileItemList.h" #include "Picture.h" #include "ServiceBroker.h" #include "TextureCache.h" diff --git a/xbmc/platform/android/activity/CMakeLists.txt b/xbmc/platform/android/activity/CMakeLists.txt index fddcec8525..55714df929 100644 --- a/xbmc/platform/android/activity/CMakeLists.txt +++ b/xbmc/platform/android/activity/CMakeLists.txt @@ -16,6 +16,7 @@ set(SOURCES android_main.cpp JNIXBMCNsdManagerResolveListener.cpp JNIXBMCJsonHandler.cpp JNIXBMCFile.cpp + JNIXBMCTextureCache.cpp JNIXBMCURIUtils.cpp JNIXBMCDisplayManagerDisplayListener.cpp JNIXBMCSpeechRecognitionListener.cpp @@ -42,6 +43,7 @@ set(HEADERS AndroidFeatures.h JNIXBMCNsdManagerResolveListener.h JNIXBMCJsonHandler.h JNIXBMCFile.h + JNIXBMCTextureCache.h JNIXBMCURIUtils.h JNIXBMCDisplayManagerDisplayListener.h JNIXBMCSpeechRecognitionListener.h diff --git a/xbmc/platform/android/activity/JNIXBMCTextureCache.cpp b/xbmc/platform/android/activity/JNIXBMCTextureCache.cpp new file mode 100644 index 0000000000..bacb4a826d --- /dev/null +++ b/xbmc/platform/android/activity/JNIXBMCTextureCache.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 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 "JNIXBMCTextureCache.h" + +#include "CompileInfo.h" +#include "TextureCache.h" + +#include <androidjni/Context.h> +#include <androidjni/jutils-details.hpp> + +using namespace jni; + +static std::string s_className = std::string(CCompileInfo::GetClass()) + "/XBMCTextureCache"; + +void CJNIXBMCTextureCache::RegisterNatives(JNIEnv* env) +{ + jclass cClass = env->FindClass(s_className.c_str()); + if (cClass) + { + JNINativeMethod methods[] = { + {"_unwrapImageURL", "(Ljava/lang/String;)Ljava/lang/String;", + (void*)&CJNIXBMCTextureCache::_unwrapImageURL}, + }; + + env->RegisterNatives(cClass, methods, sizeof(methods) / sizeof(methods[0])); + } +} + +jstring CJNIXBMCTextureCache::_unwrapImageURL(JNIEnv* env, jobject thiz, jstring image) +{ + std::string strImage = jcast<std::string>(jhstring::fromJNI(image)); + std::string responseData = CTextureUtils::UnwrapImageURL(strImage); + + jstring jres = env->NewStringUTF(responseData.c_str()); + return jres; +} diff --git a/xbmc/platform/android/activity/JNIXBMCTextureCache.h b/xbmc/platform/android/activity/JNIXBMCTextureCache.h new file mode 100644 index 0000000000..92da6e91d5 --- /dev/null +++ b/xbmc/platform/android/activity/JNIXBMCTextureCache.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 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 <androidjni/JNIBase.h> + +namespace jni +{ + +class CJNIXBMCTextureCache : public CJNIBase +{ +public: + CJNIXBMCTextureCache(const jni::jhobject& object) : CJNIBase(object) {} + + static void RegisterNatives(JNIEnv* env); + +protected: + ~CJNIXBMCTextureCache() override = default; + + static jstring _unwrapImageURL(JNIEnv* env, jobject thiz, jstring image); +}; + +} // namespace jni diff --git a/xbmc/platform/android/activity/XBMCApp.cpp b/xbmc/platform/android/activity/XBMCApp.cpp index 30e6028fb9..437c7371d9 100644 --- a/xbmc/platform/android/activity/XBMCApp.cpp +++ b/xbmc/platform/android/activity/XBMCApp.cpp @@ -47,6 +47,7 @@ #include "utils/URIUtils.h" #include "utils/Variant.h" #include "utils/log.h" +#include "video/VideoFileItemClassify.h" #include "video/VideoInfoTag.h" #include "windowing/GraphicContext.h" #include "windowing/WinEvents.h" @@ -117,6 +118,7 @@ using namespace ANNOUNCEMENT; using namespace jni; using namespace KODI::GUILIB; +using namespace KODI::VIDEO; using namespace std::chrono_literals; std::shared_ptr<CNativeWindow> CNativeWindow::CreateFromSurface(CJNISurfaceHolder holder) @@ -1451,7 +1453,7 @@ void CXBMCApp::onNewIntent(CJNIIntent intent) else { CFileItem* item = new CFileItem(targetFile, false); - if (item->IsVideoDb()) + if (IsVideoDb(*item)) { *(item->GetVideoInfoTag()) = XFILE::CVideoDatabaseFile::GetVideoTag(CURL(item->GetPath())); item->SetPath(item->GetVideoInfoTag()->m_strFileNameAndPath); diff --git a/xbmc/platform/android/activity/android_main.cpp b/xbmc/platform/android/activity/android_main.cpp index 3970e78f49..a934b6ee1c 100644 --- a/xbmc/platform/android/activity/android_main.cpp +++ b/xbmc/platform/android/activity/android_main.cpp @@ -23,6 +23,7 @@ #include "platform/android/activity/JNIXBMCNsdManagerResolveListener.h" #include "platform/android/activity/JNIXBMCSpeechRecognitionListener.h" #include "platform/android/activity/JNIXBMCSurfaceTextureOnFrameAvailableListener.h" +#include "platform/android/activity/JNIXBMCTextureCache.h" #include "platform/android/activity/JNIXBMCURIUtils.h" #include "platform/android/activity/JNIXBMCVideoView.h" @@ -127,6 +128,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) CJNIXBMCNsdManagerResolveListener::RegisterNatives(env); CJNIXBMCSpeechRecognitionListener::RegisterNatives(env); CJNIXBMCSurfaceTextureOnFrameAvailableListener::RegisterNatives(env); + CJNIXBMCTextureCache::RegisterNatives(env); CJNIXBMCURIUtils::RegisterNatives(env); CJNIXBMCVideoView::RegisterNatives(env); diff --git a/xbmc/platform/android/filesystem/APKDirectory.cpp b/xbmc/platform/android/filesystem/APKDirectory.cpp index df890bfed6..4cdcf5c529 100644 --- a/xbmc/platform/android/filesystem/APKDirectory.cpp +++ b/xbmc/platform/android/filesystem/APKDirectory.cpp @@ -10,6 +10,7 @@ #include "APKFile.h" #include "FileItem.h" +#include "FileItemList.h" #include "utils/CharsetConverter.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" diff --git a/xbmc/platform/android/filesystem/AndroidAppDirectory.cpp b/xbmc/platform/android/filesystem/AndroidAppDirectory.cpp index c2af2aae47..132f666618 100644 --- a/xbmc/platform/android/filesystem/AndroidAppDirectory.cpp +++ b/xbmc/platform/android/filesystem/AndroidAppDirectory.cpp @@ -10,6 +10,7 @@ #include "CompileInfo.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "filesystem/File.h" #include "utils/StringUtils.h" diff --git a/xbmc/platform/darwin/tvos/TVOSTopShelf.mm b/xbmc/platform/darwin/tvos/TVOSTopShelf.mm index 94690fea00..fb4770f5cd 100644 --- a/xbmc/platform/darwin/tvos/TVOSTopShelf.mm +++ b/xbmc/platform/darwin/tvos/TVOSTopShelf.mm @@ -10,6 +10,7 @@ #include "DatabaseManager.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "application/Application.h" #include "filesystem/File.h" diff --git a/xbmc/platform/darwin/tvos/filesystem/TVOSDirectory.cpp b/xbmc/platform/darwin/tvos/filesystem/TVOSDirectory.cpp index 0463943505..d0d25df5d6 100644 --- a/xbmc/platform/darwin/tvos/filesystem/TVOSDirectory.cpp +++ b/xbmc/platform/darwin/tvos/filesystem/TVOSDirectory.cpp @@ -21,6 +21,7 @@ #include "TVOSDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "filesystem/SpecialProtocol.h" #include "utils/URIUtils.h" diff --git a/xbmc/platform/posix/filesystem/PosixDirectory.cpp b/xbmc/platform/posix/filesystem/PosixDirectory.cpp index 6685c0e1db..761b8d53b4 100644 --- a/xbmc/platform/posix/filesystem/PosixDirectory.cpp +++ b/xbmc/platform/posix/filesystem/PosixDirectory.cpp @@ -9,6 +9,7 @@ #include "PosixDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "utils/AliasShortcutUtils.h" #include "utils/CharsetConverter.h" diff --git a/xbmc/platform/posix/filesystem/SMBDirectory.cpp b/xbmc/platform/posix/filesystem/SMBDirectory.cpp index e2305afb4a..12fe62683e 100644 --- a/xbmc/platform/posix/filesystem/SMBDirectory.cpp +++ b/xbmc/platform/posix/filesystem/SMBDirectory.cpp @@ -20,6 +20,7 @@ #include "SMBDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "PasswordManager.h" #include "ServiceBroker.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/platform/posix/filesystem/SMBWSDiscovery.cpp b/xbmc/platform/posix/filesystem/SMBWSDiscovery.cpp index 8bab0aa9e9..c2f247da10 100644 --- a/xbmc/platform/posix/filesystem/SMBWSDiscovery.cpp +++ b/xbmc/platform/posix/filesystem/SMBWSDiscovery.cpp @@ -9,6 +9,7 @@ #include "SMBWSDiscovery.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "network/IWSDiscovery.h" #include "utils/StringUtils.h" diff --git a/xbmc/platform/win10/filesystem/WinLibraryDirectory.cpp b/xbmc/platform/win10/filesystem/WinLibraryDirectory.cpp index bba7074400..4bd0a0db4c 100644 --- a/xbmc/platform/win10/filesystem/WinLibraryDirectory.cpp +++ b/xbmc/platform/win10/filesystem/WinLibraryDirectory.cpp @@ -9,6 +9,7 @@ #include "WinLibraryDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" diff --git a/xbmc/platform/win32/filesystem/Win32Directory.cpp b/xbmc/platform/win32/filesystem/Win32Directory.cpp index 5e4050fdd4..3d06e8dfbc 100644 --- a/xbmc/platform/win32/filesystem/Win32Directory.cpp +++ b/xbmc/platform/win32/filesystem/Win32Directory.cpp @@ -9,6 +9,7 @@ #include "Win32Directory.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "utils/CharsetConverter.h" #include "utils/SystemInfo.h" diff --git a/xbmc/platform/win32/filesystem/Win32SMBDirectory.cpp b/xbmc/platform/win32/filesystem/Win32SMBDirectory.cpp index 2075f957c8..c227351ad4 100644 --- a/xbmc/platform/win32/filesystem/Win32SMBDirectory.cpp +++ b/xbmc/platform/win32/filesystem/Win32SMBDirectory.cpp @@ -9,6 +9,7 @@ #include "Win32SMBDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "PasswordManager.h" #include "ServiceBroker.h" #include "URL.h" diff --git a/xbmc/playlists/PlayList.cpp b/xbmc/playlists/PlayList.cpp index 82031bad2e..b47c782541 100644 --- a/xbmc/playlists/PlayList.cpp +++ b/xbmc/playlists/PlayList.cpp @@ -9,6 +9,7 @@ #include "PlayList.h" #include "FileItem.h" +#include "FileItemList.h" #include "PlayListFactory.h" #include "ServiceBroker.h" #include "filesystem/File.h" diff --git a/xbmc/playlists/SmartPlaylistFileItemListModifier.cpp b/xbmc/playlists/SmartPlaylistFileItemListModifier.cpp index 7249bb5c0d..443dabcd4e 100644 --- a/xbmc/playlists/SmartPlaylistFileItemListModifier.cpp +++ b/xbmc/playlists/SmartPlaylistFileItemListModifier.cpp @@ -9,6 +9,7 @@ #include "SmartPlaylistFileItemListModifier.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "playlists/SmartPlayList.h" #include "utils/StringUtils.h" diff --git a/xbmc/profiles/dialogs/GUIDialogProfileSettings.cpp b/xbmc/profiles/dialogs/GUIDialogProfileSettings.cpp index dcdf8c47a4..9f455c4a6b 100644 --- a/xbmc/profiles/dialogs/GUIDialogProfileSettings.cpp +++ b/xbmc/profiles/dialogs/GUIDialogProfileSettings.cpp @@ -9,6 +9,7 @@ #include "GUIDialogProfileSettings.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "ServiceBroker.h" #include "Util.h" diff --git a/xbmc/profiles/windows/GUIWindowSettingsProfile.cpp b/xbmc/profiles/windows/GUIWindowSettingsProfile.cpp index d3690adb63..503516c0f6 100644 --- a/xbmc/profiles/windows/GUIWindowSettingsProfile.cpp +++ b/xbmc/profiles/windows/GUIWindowSettingsProfile.cpp @@ -9,6 +9,7 @@ #include "GUIWindowSettingsProfile.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "dialogs/GUIDialogContextMenu.h" #include "dialogs/GUIDialogSelect.h" diff --git a/xbmc/programs/GUIViewStatePrograms.cpp b/xbmc/programs/GUIViewStatePrograms.cpp index 05e4cfd978..0b08a42864 100644 --- a/xbmc/programs/GUIViewStatePrograms.cpp +++ b/xbmc/programs/GUIViewStatePrograms.cpp @@ -9,6 +9,7 @@ #include "GUIViewStatePrograms.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "filesystem/Directory.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/programs/GUIWindowPrograms.cpp b/xbmc/programs/GUIWindowPrograms.cpp index 862bdb2249..7a57f1cc0b 100644 --- a/xbmc/programs/GUIWindowPrograms.cpp +++ b/xbmc/programs/GUIWindowPrograms.cpp @@ -10,6 +10,7 @@ #include "Autorun.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "ServiceBroker.h" #include "Util.h" diff --git a/xbmc/pvr/PVRChannelGroupImageFileLoader.cpp b/xbmc/pvr/PVRChannelGroupImageFileLoader.cpp index e539ca55bd..b66ef00902 100644 --- a/xbmc/pvr/PVRChannelGroupImageFileLoader.cpp +++ b/xbmc/pvr/PVRChannelGroupImageFileLoader.cpp @@ -9,6 +9,7 @@ #include "PVRChannelGroupImageFileLoader.h" #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/PVRGUIDirectory.h" #include "guilib/Texture.h" #include "pictures/Picture.h" diff --git a/xbmc/pvr/PVRThumbLoader.cpp b/xbmc/pvr/PVRThumbLoader.cpp index 3f5fa63822..8f41a80b0c 100644 --- a/xbmc/pvr/PVRThumbLoader.cpp +++ b/xbmc/pvr/PVRThumbLoader.cpp @@ -9,6 +9,7 @@ #include "PVRThumbLoader.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "TextureCache.h" #include "pvr/PVRManager.h" diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelGuide.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelGuide.cpp index b057b338bc..563aa126cd 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRChannelGuide.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelGuide.cpp @@ -9,6 +9,7 @@ #include "GUIDialogPVRChannelGuide.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "pvr/PVRManager.h" #include "pvr/PVRPlaybackState.h" diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp index d6665fcf4b..efae8e7279 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp @@ -9,6 +9,7 @@ #include "GUIDialogPVRChannelManager.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "ServiceBroker.h" #include "TextureCache.h" diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp index 9c079c8e7e..c349bd0623 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp @@ -9,6 +9,7 @@ #include "GUIDialogPVRChannelsOSD.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "ServiceBroker.h" #include "guilib/GUIComponent.h" diff --git a/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp b/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp index c0d6d801d7..1fa8cd5175 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp @@ -9,6 +9,7 @@ #include "GUIDialogPVRGroupManager.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "dialogs/GUIDialogContextMenu.h" #include "dialogs/GUIDialogYesNo.h" diff --git a/xbmc/pvr/dialogs/GUIDialogPVRItemsViewBase.cpp b/xbmc/pvr/dialogs/GUIDialogPVRItemsViewBase.cpp index 2add783cf2..72b4694528 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRItemsViewBase.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRItemsViewBase.cpp @@ -10,6 +10,7 @@ #include "ContextMenuManager.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "dialogs/GUIDialogContextMenu.h" #include "input/actions/Action.h" diff --git a/xbmc/pvr/filesystem/PVRGUIDirectory.cpp b/xbmc/pvr/filesystem/PVRGUIDirectory.cpp index 8def92d871..2b15428347 100644 --- a/xbmc/pvr/filesystem/PVRGUIDirectory.cpp +++ b/xbmc/pvr/filesystem/PVRGUIDirectory.cpp @@ -9,6 +9,7 @@ #include "PVRGUIDirectory.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "guilib/LocalizeStrings.h" #include "guilib/WindowIDs.h" diff --git a/xbmc/pvr/guilib/GUIEPGGridContainer.cpp b/xbmc/pvr/guilib/GUIEPGGridContainer.cpp index de3ef1059e..d990f3f9db 100644 --- a/xbmc/pvr/guilib/GUIEPGGridContainer.cpp +++ b/xbmc/pvr/guilib/GUIEPGGridContainer.cpp @@ -9,6 +9,7 @@ #include "GUIEPGGridContainer.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "guilib/DirtyRegion.h" #include "guilib/GUIAction.h" diff --git a/xbmc/pvr/guilib/GUIEPGGridContainerModel.cpp b/xbmc/pvr/guilib/GUIEPGGridContainerModel.cpp index f99515160c..df6f7e41cd 100644 --- a/xbmc/pvr/guilib/GUIEPGGridContainerModel.cpp +++ b/xbmc/pvr/guilib/GUIEPGGridContainerModel.cpp @@ -9,6 +9,7 @@ #include "GUIEPGGridContainerModel.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "pvr/PVRManager.h" #include "pvr/channels/PVRChannel.h" diff --git a/xbmc/pvr/guilib/PVRGUIActionsDatabase.cpp b/xbmc/pvr/guilib/PVRGUIActionsDatabase.cpp index 53bbf815f6..1bf613dc4e 100644 --- a/xbmc/pvr/guilib/PVRGUIActionsDatabase.cpp +++ b/xbmc/pvr/guilib/PVRGUIActionsDatabase.cpp @@ -9,6 +9,7 @@ #include "PVRGUIActionsDatabase.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "dialogs/GUIDialogProgress.h" #include "dialogs/GUIDialogSelect.h" diff --git a/xbmc/pvr/guilib/PVRGUIActionsPlayback.cpp b/xbmc/pvr/guilib/PVRGUIActionsPlayback.cpp index 15c8af4208..ed11f9ec2a 100644 --- a/xbmc/pvr/guilib/PVRGUIActionsPlayback.cpp +++ b/xbmc/pvr/guilib/PVRGUIActionsPlayback.cpp @@ -9,6 +9,7 @@ #include "PVRGUIActionsPlayback.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "application/ApplicationEnums.h" #include "cores/DataCacheCore.h" diff --git a/xbmc/pvr/guilib/PVRGUIActionsRecordings.cpp b/xbmc/pvr/guilib/PVRGUIActionsRecordings.cpp index c69c909b9a..9609617be9 100644 --- a/xbmc/pvr/guilib/PVRGUIActionsRecordings.cpp +++ b/xbmc/pvr/guilib/PVRGUIActionsRecordings.cpp @@ -9,6 +9,7 @@ #include "PVRGUIActionsRecordings.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "Util.h" #include "dialogs/GUIDialogBusy.h" diff --git a/xbmc/pvr/guilib/PVRGUIActionsUtils.cpp b/xbmc/pvr/guilib/PVRGUIActionsUtils.cpp index 907c645dd3..c6399f1a26 100644 --- a/xbmc/pvr/guilib/PVRGUIActionsUtils.cpp +++ b/xbmc/pvr/guilib/PVRGUIActionsUtils.cpp @@ -9,6 +9,7 @@ #include "PVRGUIActionsUtils.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "filesystem/Directory.h" #include "pvr/PVRManager.h" diff --git a/xbmc/pvr/guilib/PVRGUIChannelIconUpdater.cpp b/xbmc/pvr/guilib/PVRGUIChannelIconUpdater.cpp index 26859dd63a..11045c98d8 100644 --- a/xbmc/pvr/guilib/PVRGUIChannelIconUpdater.cpp +++ b/xbmc/pvr/guilib/PVRGUIChannelIconUpdater.cpp @@ -9,6 +9,7 @@ #include "PVRGUIChannelIconUpdater.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "Util.h" #include "filesystem/Directory.h" diff --git a/xbmc/pvr/windows/GUIViewStatePVR.cpp b/xbmc/pvr/windows/GUIViewStatePVR.cpp index d86f6fc2a6..a5004d8ba9 100644 --- a/xbmc/pvr/windows/GUIViewStatePVR.cpp +++ b/xbmc/pvr/windows/GUIViewStatePVR.cpp @@ -9,6 +9,7 @@ #include "GUIViewStatePVR.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "pvr/PVRManager.h" #include "pvr/addons/PVRClients.h" diff --git a/xbmc/pvr/windows/GUIWindowPVRBase.cpp b/xbmc/pvr/windows/GUIWindowPVRBase.cpp index 71a800feda..ce891a80f7 100644 --- a/xbmc/pvr/windows/GUIWindowPVRBase.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRBase.cpp @@ -9,6 +9,7 @@ #include "GUIWindowPVRBase.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" #include "addons/AddonManager.h" diff --git a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp index e323c319be..8ccbdd68fa 100644 --- a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp @@ -9,6 +9,7 @@ #include "GUIWindowPVRChannels.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "ServiceBroker.h" #include "dialogs/GUIDialogContextMenu.h" diff --git a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp index 3923cae6bb..6ce75fd5f2 100644 --- a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp @@ -9,6 +9,7 @@ #include "GUIWindowPVRGuide.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" #include "addons/Skin.h" diff --git a/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp index 363011a379..284bebb93e 100644 --- a/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp @@ -8,6 +8,7 @@ #include "GUIWindowPVRRecordings.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "ServiceBroker.h" #include "guilib/GUIComponent.h" diff --git a/xbmc/pvr/windows/GUIWindowPVRSearch.cpp b/xbmc/pvr/windows/GUIWindowPVRSearch.cpp index 0c129c3e00..4a9ad6b10e 100644 --- a/xbmc/pvr/windows/GUIWindowPVRSearch.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRSearch.cpp @@ -9,6 +9,7 @@ #include "GUIWindowPVRSearch.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "dialogs/GUIDialogBusy.h" #include "dialogs/GUIDialogYesNo.h" diff --git a/xbmc/pvr/windows/GUIWindowPVRTimerRules.cpp b/xbmc/pvr/windows/GUIWindowPVRTimerRules.cpp index 1b203d403d..1d532fa1ac 100644 --- a/xbmc/pvr/windows/GUIWindowPVRTimerRules.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRTimerRules.cpp @@ -9,6 +9,7 @@ #include "GUIWindowPVRTimerRules.h" #include "FileItem.h" +#include "FileItemList.h" #include "pvr/timers/PVRTimersPath.h" #include "utils/URIUtils.h" diff --git a/xbmc/pvr/windows/GUIWindowPVRTimers.cpp b/xbmc/pvr/windows/GUIWindowPVRTimers.cpp index 610571bcd5..0bc955d6c8 100644 --- a/xbmc/pvr/windows/GUIWindowPVRTimers.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRTimers.cpp @@ -9,6 +9,7 @@ #include "GUIWindowPVRTimers.h" #include "FileItem.h" +#include "FileItemList.h" #include "pvr/timers/PVRTimersPath.h" #include "utils/URIUtils.h" diff --git a/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp b/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp index 41677eb873..68b1501e2b 100644 --- a/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp @@ -9,6 +9,7 @@ #include "GUIWindowPVRTimersBase.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "ServiceBroker.h" #include "guilib/GUIComponent.h" diff --git a/xbmc/rendering/gl/GLShader.cpp b/xbmc/rendering/gl/GLShader.cpp index e91af97b56..77dd6e4ed2 100644 --- a/xbmc/rendering/gl/GLShader.cpp +++ b/xbmc/rendering/gl/GLShader.cpp @@ -1,12 +1,11 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-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 "GLShader.h" #include "ServiceBroker.h" @@ -49,6 +48,9 @@ void CGLShader::OnCompiledAndLinked() // Variables passed directly to the Vertex shader m_hProj = glGetUniformLocation(ProgramHandle(), "m_proj"); m_hModel = glGetUniformLocation(ProgramHandle(), "m_model"); + m_hMatrix = glGetUniformLocation(ProgramHandle(), "m_matrix"); + m_hShaderClip = glGetUniformLocation(ProgramHandle(), "m_shaderClip"); + m_hCoordStep = glGetUniformLocation(ProgramHandle(), "m_cordStep"); // Vertex attributes m_hPos = glGetAttribLocation(ProgramHandle(), "m_attrpos"); diff --git a/xbmc/rendering/gl/GLShader.h b/xbmc/rendering/gl/GLShader.h index d5b82f3a07..791c44926b 100644 --- a/xbmc/rendering/gl/GLShader.h +++ b/xbmc/rendering/gl/GLShader.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2024 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -27,6 +27,9 @@ public: GLint GetCord1Loc() {return m_hCord1;} GLint GetUniColLoc() {return m_hUniCol;} GLint GetModelLoc() {return m_hModel; } + GLint GetMatrixLoc() { return m_hMatrix; } + GLint GetShaderClipLoc() { return m_hShaderClip; } + GLint GetShaderCoordStepLoc() { return m_hCoordStep; } bool HardwareClipIsPossible() {return m_clipPossible; } GLfloat GetClipXFactor() {return m_clipXFactor; } GLfloat GetClipXOffset() {return m_clipXOffset; } @@ -39,6 +42,9 @@ protected: GLint m_hUniCol = 0; GLint m_hProj = 0; GLint m_hModel = 0; + GLint m_hMatrix{0}; // m_hProj * m_hModel + GLint m_hShaderClip{0}; // clipping rect vec4(x1,y1,x2,y2) + GLint m_hCoordStep{0}; // step (1/resolution) for the two textures vec4(t1.x,t1.y,t2.x,t2.y) GLint m_hPos = 0; GLint m_hCol = 0; GLint m_hCord0 = 0; diff --git a/xbmc/rendering/gl/RenderSystemGL.cpp b/xbmc/rendering/gl/RenderSystemGL.cpp index 4b80014d41..516027ef49 100644 --- a/xbmc/rendering/gl/RenderSystemGL.cpp +++ b/xbmc/rendering/gl/RenderSystemGL.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2024 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -682,13 +682,24 @@ void CRenderSystemGL::InitialiseShaders() CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_multi.glsl - compile and link failed"); } - m_pShader[ShaderMethodGL::SM_FONTS] = - std::make_unique<CGLShader>("gl_shader_frag_fonts.glsl", defines); + m_pShader[ShaderMethodGL::SM_FONTS] = std::make_unique<CGLShader>( + "gl_shader_vert_simple.glsl", "gl_shader_frag_fonts.glsl", defines); if (!m_pShader[ShaderMethodGL::SM_FONTS]->CompileAndLink()) { m_pShader[ShaderMethodGL::SM_FONTS]->Free(); m_pShader[ShaderMethodGL::SM_FONTS].reset(); - CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_fonts.glsl - compile and link failed"); + CLog::Log(LOGERROR, "GUI Shader gl_shader_vert_simple.glsl + gl_shader_frag_fonts.glsl - " + "compile and link failed"); + } + + m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP] = + std::make_unique<CGLShader>("gl_shader_vert_clip.glsl", "gl_shader_frag_fonts.glsl", defines); + if (!m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP]->CompileAndLink()) + { + m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP]->Free(); + m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP].reset(); + CLog::Log(LOGERROR, "GUI Shader gl_shader_vert_clip.glsl + gl_shader_frag_fonts.glsl - compile " + "and link failed"); } m_pShader[ShaderMethodGL::SM_TEXTURE_NOBLEND] = @@ -732,6 +743,10 @@ void CRenderSystemGL::ReleaseShaders() m_pShader[ShaderMethodGL::SM_FONTS]->Free(); m_pShader[ShaderMethodGL::SM_FONTS].reset(); + if (m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP]) + m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP]->Free(); + m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP].reset(); + if (m_pShader[ShaderMethodGL::SM_TEXTURE_NOBLEND]) m_pShader[ShaderMethodGL::SM_TEXTURE_NOBLEND]->Free(); m_pShader[ShaderMethodGL::SM_TEXTURE_NOBLEND].reset(); @@ -811,6 +826,30 @@ GLint CRenderSystemGL::ShaderGetModel() return -1; } +GLint CRenderSystemGL::ShaderGetMatrix() +{ + if (m_pShader[m_method]) + return m_pShader[m_method]->GetMatrixLoc(); + + return -1; +} + +GLint CRenderSystemGL::ShaderGetClip() +{ + if (m_pShader[m_method]) + return m_pShader[m_method]->GetShaderClipLoc(); + + return -1; +} + +GLint CRenderSystemGL::ShaderGetCoordStep() +{ + if (m_pShader[m_method]) + return m_pShader[m_method]->GetShaderCoordStepLoc(); + + return -1; +} + std::string CRenderSystemGL::GetShaderPath(const std::string &filename) { std::string path = "GL/1.2/"; diff --git a/xbmc/rendering/gl/RenderSystemGL.h b/xbmc/rendering/gl/RenderSystemGL.h index 191c97ff96..520c552e45 100644 --- a/xbmc/rendering/gl/RenderSystemGL.h +++ b/xbmc/rendering/gl/RenderSystemGL.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2024 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -27,6 +27,7 @@ enum class ShaderMethodGL SM_TEXTURE_LIM, SM_MULTI, SM_FONTS, + SM_FONTS_SHADER_CLIP, SM_TEXTURE_NOBLEND, SM_MULTI_BLENDCOLOR, SM_MAX @@ -52,6 +53,7 @@ private: {ShaderMethodGL::SM_TEXTURE_LIM, "texture limited"}, {ShaderMethodGL::SM_MULTI, "multi"}, {ShaderMethodGL::SM_FONTS, "fonts"}, + {ShaderMethodGL::SM_FONTS_SHADER_CLIP, "fonts with vertex shader based clipping"}, {ShaderMethodGL::SM_TEXTURE_NOBLEND, "texture no blending"}, {ShaderMethodGL::SM_MULTI_BLENDCOLOR, "multi blend colour"}, }); @@ -114,6 +116,9 @@ public: GLint ShaderGetCoord1(); GLint ShaderGetUniCol(); GLint ShaderGetModel(); + GLint ShaderGetMatrix(); + GLint ShaderGetClip(); + GLint ShaderGetCoordStep(); protected: virtual void SetVSyncImpl(bool enable) = 0; diff --git a/xbmc/rendering/gles/GLESShader.cpp b/xbmc/rendering/gles/GLESShader.cpp index 961c3f7961..ba7b83175d 100644 --- a/xbmc/rendering/gles/GLESShader.cpp +++ b/xbmc/rendering/gles/GLESShader.cpp @@ -54,6 +54,9 @@ void CGLESShader::OnCompiledAndLinked() m_hProj = glGetUniformLocation(ProgramHandle(), "m_proj"); m_hModel = glGetUniformLocation(ProgramHandle(), "m_model"); m_hCoord0Matrix = glGetUniformLocation(ProgramHandle(), "m_coord0Matrix"); + m_hMatrix = glGetUniformLocation(ProgramHandle(), "m_matrix"); + m_hShaderClip = glGetUniformLocation(ProgramHandle(), "m_shaderClip"); + m_hCoordStep = glGetUniformLocation(ProgramHandle(), "m_cordStep"); // Vertex attributes m_hPos = glGetAttribLocation(ProgramHandle(), "m_attrpos"); diff --git a/xbmc/rendering/gles/GLESShader.h b/xbmc/rendering/gles/GLESShader.h index 1f59895740..ddc31202c5 100644 --- a/xbmc/rendering/gles/GLESShader.h +++ b/xbmc/rendering/gles/GLESShader.h @@ -32,6 +32,9 @@ public: GLint GetContrastLoc() { return m_hContrast; } GLint GetBrightnessLoc() { return m_hBrightness; } GLint GetModelLoc() { return m_hModel; } + GLint GetMatrixLoc() { return m_hMatrix; } + GLint GetShaderClipLoc() { return m_hShaderClip; } + GLint GetShaderCoordStepLoc() { return m_hCoordStep; } bool HardwareClipIsPossible() { return m_clipPossible; } GLfloat GetClipXFactor() { return m_clipXFactor; } GLfloat GetClipXOffset() { return m_clipXOffset; } @@ -44,6 +47,9 @@ protected: GLint m_hUniCol = 0; GLint m_hProj = 0; GLint m_hModel = 0; + GLint m_hMatrix{0}; // m_hProj * m_hModel + GLint m_hShaderClip{0}; // clipping rect vec4(x1,y1,x2,y2) + GLint m_hCoordStep{0}; // step (1/resolution) for the two textures vec4(t1.x,t1.y,t2.x,t2.y) GLint m_hPos = 0; GLint m_hCol = 0; GLint m_hCord0 = 0; diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp index f25f783960..a5c02803b0 100644 --- a/xbmc/rendering/gles/RenderSystemGLES.cpp +++ b/xbmc/rendering/gles/RenderSystemGLES.cpp @@ -425,7 +425,7 @@ void CRenderSystemGLES::InitialiseShaders() } m_pShader[ShaderMethodGLES::SM_FONTS] = - std::make_unique<CGLESShader>("gles_shader_fonts.frag", defines); + std::make_unique<CGLESShader>("gles_shader_simple.vert", "gles_shader_fonts.frag", defines); if (!m_pShader[ShaderMethodGLES::SM_FONTS]->CompileAndLink()) { m_pShader[ShaderMethodGLES::SM_FONTS]->Free(); @@ -433,6 +433,16 @@ void CRenderSystemGLES::InitialiseShaders() CLog::Log(LOGERROR, "GUI Shader gles_shader_fonts.frag - compile and link failed"); } + m_pShader[ShaderMethodGLES::SM_FONTS_SHADER_CLIP] = + std::make_unique<CGLESShader>("gles_shader_clip.vert", "gles_shader_fonts.frag", defines); + if (!m_pShader[ShaderMethodGLES::SM_FONTS_SHADER_CLIP]->CompileAndLink()) + { + m_pShader[ShaderMethodGLES::SM_FONTS_SHADER_CLIP]->Free(); + m_pShader[ShaderMethodGLES::SM_FONTS_SHADER_CLIP].reset(); + CLog::Log(LOGERROR, "GUI Shader gles_shader_clip.vert + gles_shader_fonts.frag - compile " + "and link failed"); + } + m_pShader[ShaderMethodGLES::SM_TEXTURE_NOBLEND] = std::make_unique<CGLESShader>("gles_shader_texture_noblend.frag", defines); if (!m_pShader[ShaderMethodGLES::SM_TEXTURE_NOBLEND]->CompileAndLink()) @@ -528,6 +538,10 @@ void CRenderSystemGLES::ReleaseShaders() m_pShader[ShaderMethodGLES::SM_FONTS]->Free(); m_pShader[ShaderMethodGLES::SM_FONTS].reset(); + if (m_pShader[ShaderMethodGLES::SM_FONTS_SHADER_CLIP]) + m_pShader[ShaderMethodGLES::SM_FONTS_SHADER_CLIP]->Free(); + m_pShader[ShaderMethodGLES::SM_FONTS_SHADER_CLIP].reset(); + if (m_pShader[ShaderMethodGLES::SM_TEXTURE_NOBLEND]) m_pShader[ShaderMethodGLES::SM_TEXTURE_NOBLEND]->Free(); m_pShader[ShaderMethodGLES::SM_TEXTURE_NOBLEND].reset(); @@ -675,3 +689,27 @@ GLint CRenderSystemGLES::GUIShaderGetModel() return -1; } + +GLint CRenderSystemGLES::GUIShaderGetMatrix() +{ + if (m_pShader[m_method]) + return m_pShader[m_method]->GetMatrixLoc(); + + return -1; +} + +GLint CRenderSystemGLES::GUIShaderGetClip() +{ + if (m_pShader[m_method]) + return m_pShader[m_method]->GetShaderClipLoc(); + + return -1; +} + +GLint CRenderSystemGLES::GUIShaderGetCoordStep() +{ + if (m_pShader[m_method]) + return m_pShader[m_method]->GetShaderCoordStepLoc(); + + return -1; +} diff --git a/xbmc/rendering/gles/RenderSystemGLES.h b/xbmc/rendering/gles/RenderSystemGLES.h index e0cd72b9c1..7986f2c0a4 100644 --- a/xbmc/rendering/gles/RenderSystemGLES.h +++ b/xbmc/rendering/gles/RenderSystemGLES.h @@ -25,6 +25,7 @@ enum class ShaderMethodGLES SM_TEXTURE, SM_MULTI, SM_FONTS, + SM_FONTS_SHADER_CLIP, SM_TEXTURE_NOBLEND, SM_MULTI_BLENDCOLOR, SM_TEXTURE_RGBA, @@ -55,6 +56,7 @@ private: {ShaderMethodGLES::SM_TEXTURE, "texture"}, {ShaderMethodGLES::SM_MULTI, "multi"}, {ShaderMethodGLES::SM_FONTS, "fonts"}, + {ShaderMethodGLES::SM_FONTS_SHADER_CLIP, "fonts with vertex shader based clipping"}, {ShaderMethodGLES::SM_TEXTURE_NOBLEND, "texture no blending"}, {ShaderMethodGLES::SM_MULTI_BLENDCOLOR, "multi blend colour"}, {ShaderMethodGLES::SM_TEXTURE_RGBA, "texure rgba"}, @@ -124,6 +126,9 @@ public: GLint GUIShaderGetContrast(); GLint GUIShaderGetBrightness(); GLint GUIShaderGetModel(); + GLint GUIShaderGetMatrix(); + GLint GUIShaderGetClip(); + GLint GUIShaderGetCoordStep(); protected: virtual void SetVSyncImpl(bool enable) = 0; diff --git a/xbmc/settings/windows/GUIControlSettings.cpp b/xbmc/settings/windows/GUIControlSettings.cpp index fdb1a439fd..ea45b0deed 100644 --- a/xbmc/settings/windows/GUIControlSettings.cpp +++ b/xbmc/settings/windows/GUIControlSettings.cpp @@ -9,6 +9,7 @@ #include "GUIControlSettings.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "Util.h" #include "addons/AddonManager.h" diff --git a/xbmc/test/TestBasicEnvironment.cpp b/xbmc/test/TestBasicEnvironment.cpp index 7a357765a0..7a33e9d851 100644 --- a/xbmc/test/TestBasicEnvironment.cpp +++ b/xbmc/test/TestBasicEnvironment.cpp @@ -9,6 +9,7 @@ #include "TestBasicEnvironment.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "ServiceManager.h" #include "TestUtils.h" diff --git a/xbmc/utils/ExecString.cpp b/xbmc/utils/ExecString.cpp index cd392c26db..f4767ff958 100644 --- a/xbmc/utils/ExecString.cpp +++ b/xbmc/utils/ExecString.cpp @@ -18,8 +18,11 @@ #include "utils/StringUtils.h" #include "utils/Variant.h" #include "utils/log.h" +#include "video/VideoFileItemClassify.h" #include "video/VideoInfoTag.h" +using namespace KODI; + CExecString::CExecString(const std::string& execString) { m_valid = Parse(execString); @@ -123,7 +126,7 @@ bool CExecString::Parse(const CFileItem& item, const std::string& contextWindow) Build("StartAndroidActivity", {StringUtils::Paramify(item.GetPath().substr(26))}); else // assume a media file { - if (item.IsVideoDb() && item.HasVideoInfoTag()) + if (VIDEO::IsVideoDb(item) && item.HasVideoInfoTag()) BuildPlayMedia(item, StringUtils::Paramify(item.GetVideoInfoTag()->m_strFileNameAndPath)); else if (item.IsMusicDb() && item.HasMusicInfoTag()) BuildPlayMedia(item, StringUtils::Paramify(item.GetMusicInfoTag()->GetURL())); diff --git a/xbmc/utils/FileOperationJob.h b/xbmc/utils/FileOperationJob.h index 7284c62b6b..5dad5403bd 100644 --- a/xbmc/utils/FileOperationJob.h +++ b/xbmc/utils/FileOperationJob.h @@ -9,6 +9,7 @@ #pragma once #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/IFileTypes.h" #include "utils/ProgressJob.h" diff --git a/xbmc/utils/FontUtils.cpp b/xbmc/utils/FontUtils.cpp index 2c23b90c69..8e6af68907 100644 --- a/xbmc/utils/FontUtils.cpp +++ b/xbmc/utils/FontUtils.cpp @@ -9,6 +9,7 @@ #include "FontUtils.h" #include "FileItem.h" +#include "FileItemList.h" #include "StringUtils.h" #include "URIUtils.h" #include "filesystem/Directory.h" diff --git a/xbmc/utils/Geometry.h b/xbmc/utils/Geometry.h index 31557fc647..1bf4624d06 100644 --- a/xbmc/utils/Geometry.h +++ b/xbmc/utils/Geometry.h @@ -281,6 +281,11 @@ public: return (x1 <= point.x && point.x <= x2 && y1 <= point.y && point.y <= y2); }; + constexpr bool Intersects(const this_type& rect) const + { + return (x1 < rect.x2 && x2 > rect.x1 && y1 < rect.y2 && y2 > rect.y1); + }; + this_type& operator-=(const point_type &point) XBMC_FORCE_INLINE { x1 -= point.x; diff --git a/xbmc/utils/GroupUtils.cpp b/xbmc/utils/GroupUtils.cpp index c44af798f5..348b574880 100644 --- a/xbmc/utils/GroupUtils.cpp +++ b/xbmc/utils/GroupUtils.cpp @@ -9,6 +9,7 @@ #include "GroupUtils.h" #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/MultiPathDirectory.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" diff --git a/xbmc/utils/RecentlyAddedJob.cpp b/xbmc/utils/RecentlyAddedJob.cpp index fca1f6d997..3a845ac2ac 100644 --- a/xbmc/utils/RecentlyAddedJob.cpp +++ b/xbmc/utils/RecentlyAddedJob.cpp @@ -9,6 +9,7 @@ #include "RecentlyAddedJob.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindow.h" diff --git a/xbmc/utils/SaveFileStateJob.cpp b/xbmc/utils/SaveFileStateJob.cpp index 3f47f61e65..aeb479a4bb 100644 --- a/xbmc/utils/SaveFileStateJob.cpp +++ b/xbmc/utils/SaveFileStateJob.cpp @@ -40,7 +40,7 @@ void CSaveFileState::DoWork(CFileItem& item, if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://")) progressTrackingFile = item.GetVideoInfoTag()->m_strFileNameAndPath; // this variable contains removable:// suffixed by disc label+uniqueid or is empty if label not uniquely identified - else if (item.HasVideoInfoTag() && item.IsVideoDb()) + else if (item.HasVideoInfoTag() && IsVideoDb(item)) progressTrackingFile = item.GetVideoInfoTag()->m_strFileNameAndPath; // we need the file url of the video db item to create the bookmark else if (item.HasProperty("original_listitem_url")) { diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp index ca65b57b65..9b862a7f43 100644 --- a/xbmc/utils/URIUtils.cpp +++ b/xbmc/utils/URIUtils.cpp @@ -6,19 +6,21 @@ * See LICENSES/README.md for more information. */ -#include "network/Network.h" #include "URIUtils.h" + #include "FileItem.h" +#include "FileItemList.h" +#include "ServiceBroker.h" +#include "StringUtils.h" +#include "URL.h" #include "filesystem/MultiPathDirectory.h" #include "filesystem/SpecialProtocol.h" #include "filesystem/StackDirectory.h" #include "network/DNSNameCache.h" +#include "network/Network.h" #include "pvr/channels/PVRChannelsPath.h" #include "settings/AdvancedSettings.h" -#include "URL.h" #include "utils/FileExtensionProvider.h" -#include "ServiceBroker.h" -#include "StringUtils.h" #include "utils/log.h" #if defined(TARGET_WINDOWS) diff --git a/xbmc/utils/test/TestVariant.cpp b/xbmc/utils/test/TestVariant.cpp index f5bf687ea6..60eafddf04 100644 --- a/xbmc/utils/test/TestVariant.cpp +++ b/xbmc/utils/test/TestVariant.cpp @@ -294,7 +294,7 @@ TEST(TestVariant, empty) std::map<std::string, std::string> strmap; EXPECT_TRUE(CVariant(strmap).empty()); - strmap.emplace(std::string("key"), std::string("value")); + strmap.emplace("key", "value"); EXPECT_FALSE(CVariant(strmap).empty()); std::string str; diff --git a/xbmc/video/ContextMenus.cpp b/xbmc/video/ContextMenus.cpp index a7a724e082..1ab69f504e 100644 --- a/xbmc/video/ContextMenus.cpp +++ b/xbmc/video/ContextMenus.cpp @@ -24,6 +24,7 @@ #include "utils/ExecString.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" +#include "video/VideoFileItemClassify.h" #include "video/VideoInfoTag.h" #include "video/VideoManagerTypes.h" #include "video/VideoUtils.h" @@ -35,6 +36,8 @@ #include <utility> +using namespace KODI::VIDEO; + namespace CONTEXTMENU { @@ -87,7 +90,7 @@ bool CVideoMarkWatched::IsVisible(const CFileItem& item) const if (item.m_bIsFolder) // Only allow video db content, video and recording folders to be updated recursively { if (item.HasVideoInfoTag()) - return item.IsVideoDb(); + return IsVideoDb(item); else if (item.GetProperty("IsVideoFolder").asBoolean()) return true; else @@ -116,7 +119,7 @@ bool CVideoMarkUnWatched::IsVisible(const CFileItem& item) const if (item.m_bIsFolder) // Only allow video db content, video and recording folders to be updated recursively { if (item.HasVideoInfoTag()) - return item.IsVideoDb(); + return IsVideoDb(item); else if (item.GetProperty("IsVideoFolder").asBoolean()) return true; else @@ -237,7 +240,7 @@ bool CVideoChooseVersion::IsVisible(const CFileItem& item) const return item.HasVideoVersions() && !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( CSettings::SETTING_VIDEOLIBRARY_SHOWVIDEOVERSIONSASFOLDER) && - !VIDEO::IsVideoAssetFile(item); + !IsVideoAssetFile(item); } bool CVideoChooseVersion::Execute(const std::shared_ptr<CFileItem>& item) const @@ -272,7 +275,7 @@ std::vector<std::string> GetPlayers(const CPlayerCoreFactory& playerCoreFactory, const CFileItem& item) { std::vector<std::string> players; - if (item.IsVideoDb()) + if (IsVideoDb(item)) { //! @todo CPlayerCoreFactory and classes called from there do not handle dyn path correctly. CFileItem item2{item}; @@ -351,7 +354,7 @@ void SetPathAndPlay(const std::shared_ptr<CFileItem>& item, PlayMode mode) else { const auto itemCopy{std::make_shared<CFileItem>(*item)}; - if (itemCopy->IsVideoDb()) + if (IsVideoDb(*itemCopy)) { if (!itemCopy->m_bIsFolder) { @@ -431,7 +434,7 @@ bool CVideoPlayUsing::IsVisible(const CFileItem& item) const if (item.HasVideoVersions() && !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( CSettings::SETTING_VIDEOLIBRARY_SHOWVIDEOVERSIONSASFOLDER) && - !VIDEO::IsVideoAssetFile(item)) + !IsVideoAssetFile(item)) return false; if (item.IsLiveTV()) @@ -453,7 +456,7 @@ bool CVideoPlayVersionUsing::IsVisible(const CFileItem& item) const return item.HasVideoVersions() && !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( CSettings::SETTING_VIDEOLIBRARY_SHOWVIDEOVERSIONSASFOLDER) && - !VIDEO::IsVideoAssetFile(item); + !IsVideoAssetFile(item); } bool CVideoPlayVersionUsing::Execute(const std::shared_ptr<CFileItem>& itemIn) const diff --git a/xbmc/video/GUIViewStateVideo.cpp b/xbmc/video/GUIViewStateVideo.cpp index 278bec56b4..1cf1a0115c 100644 --- a/xbmc/video/GUIViewStateVideo.cpp +++ b/xbmc/video/GUIViewStateVideo.cpp @@ -9,6 +9,7 @@ #include "GUIViewStateVideo.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "VideoDatabase.h" #include "filesystem/Directory.h" @@ -21,8 +22,10 @@ #include "settings/SettingsComponent.h" #include "utils/FileExtensionProvider.h" #include "utils/SortUtils.h" +#include "video/VideoFileItemClassify.h" #include "view/ViewStateSettings.h" +using namespace KODI::VIDEO; using namespace XFILE; using namespace VIDEODATABASEDIRECTORY; @@ -69,7 +72,7 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it SetSortOrder(SortOrderNone); } - else if (items.IsVideoDb()) + else if (IsVideoDb(items)) { NODE_TYPE NodeType=CVideoDatabaseDirectory::GetDirectoryChildType(items.GetPath()); CQueryParams params; @@ -337,7 +340,7 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it void CGUIViewStateWindowVideoNav::SaveViewState() { - if (m_items.IsVideoDb()) + if (IsVideoDb(m_items)) { NODE_TYPE NodeType = CVideoDatabaseDirectory::GetDirectoryChildType(m_items.GetPath()); CQueryParams params; diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp index 1372e54173..a40b707a3f 100644 --- a/xbmc/video/VideoDatabase.cpp +++ b/xbmc/video/VideoDatabase.cpp @@ -9,6 +9,7 @@ #include "VideoDatabase.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "GUIPassword.h" #include "ServiceBroker.h" @@ -52,6 +53,7 @@ #include "utils/XMLUtils.h" #include "utils/log.h" #include "video/VideoDbUrl.h" +#include "video/VideoFileItemClassify.h" #include "video/VideoInfoTag.h" #include "video/VideoLibraryQueue.h" #include "video/VideoManagerTypes.h" @@ -70,6 +72,7 @@ using namespace VIDEO; using namespace ADDON; using namespace KODI::MESSAGING; using namespace KODI::GUILIB; +using namespace KODI::VIDEO; //******************************************************************************************************************************** CVideoDatabase::CVideoDatabase(void) = default; @@ -1040,7 +1043,7 @@ int CVideoDatabase::AddFile(const std::string& strFileNameAndPath, int CVideoDatabase::AddFile(const CFileItem& item) { - if (item.IsVideoDb() && item.HasVideoInfoTag()) + if (IsVideoDb(item) && item.HasVideoInfoTag()) { const auto videoInfoTag = item.GetVideoInfoTag(); if (videoInfoTag->m_iFileId != -1) diff --git a/xbmc/video/VideoFileItemClassify.cpp b/xbmc/video/VideoFileItemClassify.cpp index 65a9253f68..d57306013d 100644 --- a/xbmc/video/VideoFileItemClassify.cpp +++ b/xbmc/video/VideoFileItemClassify.cpp @@ -10,13 +10,74 @@ #include "FileItem.h" #include "ServiceBroker.h" +#include "URL.h" #include "utils/FileExtensionProvider.h" +#include "utils/FileUtils.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" +#include "video/VideoInfoTag.h" namespace KODI::VIDEO { +bool IsBDFile(const CFileItem& item) +{ + const std::string strFileName = URIUtils::GetFileName(item.GetDynPath()); + return (StringUtils::EqualsNoCase(strFileName, "index.bdmv") || + StringUtils::EqualsNoCase(strFileName, "MovieObject.bdmv") || + StringUtils::EqualsNoCase(strFileName, "INDEX.BDM") || + StringUtils::EqualsNoCase(strFileName, "MOVIEOBJ.BDM")); +} + +bool IsDiscStub(const CFileItem& item) +{ + if (IsVideoDb(item) && item.HasVideoInfoTag()) + { + CFileItem dbItem(item.m_bIsFolder ? item.GetVideoInfoTag()->m_strPath + : item.GetVideoInfoTag()->m_strFileNameAndPath, + item.m_bIsFolder); + return IsDiscStub(dbItem); + } + + return URIUtils::HasExtension(item.GetPath(), + CServiceBroker::GetFileExtensionProvider().GetDiscStubExtensions()); +} + +bool IsDVDFile(const CFileItem& item, bool bVobs /*= true*/, bool bIfos /*= true*/) +{ + const std::string strFileName = URIUtils::GetFileName(item.GetDynPath()); + if (bIfos) + { + if (StringUtils::EqualsNoCase(strFileName, "video_ts.ifo")) + return true; + if (StringUtils::StartsWithNoCase(strFileName, "vts_") && + StringUtils::EndsWithNoCase(strFileName, "_0.ifo") && strFileName.length() == 12) + return true; + } + if (bVobs) + { + if (StringUtils::EqualsNoCase(strFileName, "video_ts.vob")) + return true; + if (StringUtils::StartsWithNoCase(strFileName, "vts_") && + StringUtils::EndsWithNoCase(strFileName, ".vob")) + return true; + } + + return false; +} + +bool IsProtectedBlurayDisc(const CFileItem& item) +{ + const std::string path = URIUtils::AddFileToFolder(item.GetPath(), "AACS", "Unit_Key_RO.inf"); + return CFileUtils::Exists(path); +} + +bool IsSubtitle(const CFileItem& item) +{ + return URIUtils::HasExtension(item.GetPath(), + CServiceBroker::GetFileExtensionProvider().GetSubtitleExtensions()); +} + bool IsVideo(const CFileItem& item) { /* check preset mime type */ @@ -62,4 +123,25 @@ bool IsVideo(const CFileItem& item) CServiceBroker::GetFileExtensionProvider().GetVideoExtensions()); } +bool IsVideoAssetFile(const CFileItem& item) +{ + if (item.m_bIsFolder || !IsVideoDb(item)) + return false; + + // @todo maybe in the future look for prefix videodb://movies/videoversions in path instead + // @todo better encoding of video assets as path, they won't always be tied with movies. + return CURL(item.GetPath()).HasOption("videoversionid"); +} + +bool IsVideoDb(const CFileItem& item) +{ + return URIUtils::IsVideoDb(item.GetPath()); +} + +bool IsVideoExtrasFolder(const CFileItem& item) +{ + return item.m_bIsFolder && + StringUtils::EqualsNoCase(URIUtils::GetFileOrFolderName(item.GetPath()), "extras"); +} + } // namespace KODI::VIDEO diff --git a/xbmc/video/VideoFileItemClassify.h b/xbmc/video/VideoFileItemClassify.h index 337a0696c6..55e5aeded7 100644 --- a/xbmc/video/VideoFileItemClassify.h +++ b/xbmc/video/VideoFileItemClassify.h @@ -13,9 +13,35 @@ class CFileItem; namespace KODI::VIDEO { +//! \brief Check whether an item is a blu-ray file. +bool IsBDFile(const CFileItem& item); + +//! \brief Check whether an item is a disc stub. +bool IsDiscStub(const CFileItem& item); + +//! \brief Check whether an item is a DVD file. +bool IsDVDFile(const CFileItem& item, bool bVobs = true, bool bIfos = true); + +//! \brief Checks whether item points to a protected blu-ray disc. +bool IsProtectedBlurayDisc(const CFileItem& item); + +//! \brief Check whether an item is a subtitle file. +bool IsSubtitle(const CFileItem& item); + //! \brief Check whether an item is a video item. //! \details Note that this returns true for anything with a video info tag, //! so that may include eg. folders. bool IsVideo(const CFileItem& item); +//! \brief Is the item a video asset, excluding folders +//! \param[in] item the item +//! \return true if it is, false otherwise +bool IsVideoAssetFile(const CFileItem& item); + +//! \brief Check whether an item is a video database item. +bool IsVideoDb(const CFileItem& item); + +//! \brief Check whether an item is a video extras folder item. +bool IsVideoExtrasFolder(const CFileItem& item); + } // namespace KODI::VIDEO diff --git a/xbmc/video/VideoGeneratedImageFileLoader.cpp b/xbmc/video/VideoGeneratedImageFileLoader.cpp index e39f5960cf..6ef1b93ef9 100644 --- a/xbmc/video/VideoGeneratedImageFileLoader.cpp +++ b/xbmc/video/VideoGeneratedImageFileLoader.cpp @@ -17,8 +17,11 @@ #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "utils/URIUtils.h" +#include "video/VideoFileItemClassify.h" #include "video/VideoInfoTag.h" +using namespace KODI::VIDEO; + bool VIDEO::CVideoGeneratedImageFileLoader::CanLoad(const std::string& specialType) const { return specialType == "video"; @@ -29,7 +32,7 @@ namespace void SetupRarOptions(CFileItem& item, const std::string& path) { std::string path2(path); - if (item.IsVideoDb() && item.HasVideoInfoTag()) + if (IsVideoDb(item) && item.HasVideoInfoTag()) path2 = item.GetVideoInfoTag()->m_strFileNameAndPath; CURL url(path2); std::string opts = url.GetOptions(); @@ -40,7 +43,7 @@ void SetupRarOptions(CFileItem& item, const std::string& path) else opts = "?flags=8"; url.SetOptions(opts); - if (item.IsVideoDb() && item.HasVideoInfoTag()) + if (IsVideoDb(item) && item.HasVideoInfoTag()) item.GetVideoInfoTag()->m_strFileNameAndPath = url.Get(); else item.SetPath(url.Get()); diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp index b5559cea69..b9062bf0b1 100644 --- a/xbmc/video/VideoInfoScanner.cpp +++ b/xbmc/video/VideoInfoScanner.cpp @@ -9,6 +9,7 @@ #include "VideoInfoScanner.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" @@ -415,7 +416,7 @@ namespace VIDEO break; // add video extras to library - if (foundSomething && !m_ignoreVideoExtras && pItem->IsVideoExtras()) + if (foundSomething && !m_ignoreVideoExtras && IsVideoExtrasFolder(*pItem)) { if (AddVideoExtras(items, content, pItem->GetPath())) { diff --git a/xbmc/video/VideoItemArtworkHandler.cpp b/xbmc/video/VideoItemArtworkHandler.cpp index 038da6b405..b845b52b4c 100644 --- a/xbmc/video/VideoItemArtworkHandler.cpp +++ b/xbmc/video/VideoItemArtworkHandler.cpp @@ -9,6 +9,7 @@ #include "VideoItemArtworkHandler.h" #include "FileItem.h" +#include "FileItemList.h" #include "MediaSource.h" #include "ServiceBroker.h" #include "TextureDatabase.h" diff --git a/xbmc/video/VideoThumbLoader.cpp b/xbmc/video/VideoThumbLoader.cpp index 155fcb9da6..7119716136 100644 --- a/xbmc/video/VideoThumbLoader.cpp +++ b/xbmc/video/VideoThumbLoader.cpp @@ -9,6 +9,7 @@ #include "VideoThumbLoader.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "TextureCache.h" #include "URL.h" @@ -413,7 +414,7 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem &item) m_videoDatabase->Open(); // @todo unify asset path for other items path - if (VIDEO::IsVideoAssetFile(item)) + if (IsVideoAssetFile(item)) { if (m_videoDatabase->GetArtForAsset( tag.m_iFileId, @@ -554,7 +555,7 @@ std::string CVideoThumbLoader::GetLocalArt(const CFileItem &item, const std::str std::string CVideoThumbLoader::GetEmbeddedThumbURL(const CFileItem &item) { std::string path(item.GetPath()); - if (item.IsVideoDb() && item.HasVideoInfoTag()) + if (IsVideoDb(item) && item.HasVideoInfoTag()) path = item.GetVideoInfoTag()->m_strFileNameAndPath; if (URIUtils::IsStack(path)) path = CStackDirectory::GetFirstStackedFile(path); @@ -600,7 +601,7 @@ void CVideoThumbLoader::DetectAndAddMissingItemData(CFileItem &item) if (stereoMode.empty()) { std::string path = item.GetPath(); - if (item.IsVideoDb() && item.HasVideoInfoTag()) + if (IsVideoDb(item) && item.HasVideoInfoTag()) path = item.GetVideoInfoTag()->GetPath(); // check for custom stereomode setting in video settings diff --git a/xbmc/video/VideoUtils.cpp b/xbmc/video/VideoUtils.cpp index d3ab9fed70..cc74cb0a0f 100644 --- a/xbmc/video/VideoUtils.cpp +++ b/xbmc/video/VideoUtils.cpp @@ -9,6 +9,7 @@ #include "VideoUtils.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "Util.h" #include "filesystem/Directory.h" @@ -29,6 +30,8 @@ #include <cstdint> #include <vector> +using namespace KODI::VIDEO; + namespace { VIDEO_UTILS::ResumeInformation GetFolderItemResumeInformation(const CFileItem& item) @@ -125,13 +128,13 @@ VIDEO_UTILS::ResumeInformation GetNonFolderItemResumeInformation(const CFileItem } std::string path = item.GetPath(); - if (item.IsVideoDb() || item.IsDVD()) + if (IsVideoDb(item) || item.IsDVD()) { if (item.HasVideoInfoTag()) { path = item.GetVideoInfoTag()->m_strFileNameAndPath; } - else if (item.IsVideoDb()) + else if (IsVideoDb(item)) { // Obtain path+filename from video db XFILE::VIDEODATABASEDIRECTORY::CQueryParams params; diff --git a/xbmc/video/dialogs/GUIDialogCMSSettings.cpp b/xbmc/video/dialogs/GUIDialogCMSSettings.cpp index 6299cacbc6..c7945523ee 100644 --- a/xbmc/video/dialogs/GUIDialogCMSSettings.cpp +++ b/xbmc/video/dialogs/GUIDialogCMSSettings.cpp @@ -9,6 +9,7 @@ #include "GUIDialogCMSSettings.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "ServiceBroker.h" #include "addons/Skin.h" diff --git a/xbmc/video/dialogs/GUIDialogSubtitles.cpp b/xbmc/video/dialogs/GUIDialogSubtitles.cpp index e178a0002e..c22eda9717 100644 --- a/xbmc/video/dialogs/GUIDialogSubtitles.cpp +++ b/xbmc/video/dialogs/GUIDialogSubtitles.cpp @@ -9,6 +9,7 @@ #include "GUIDialogSubtitles.h" #include "FileItem.h" +#include "FileItemList.h" #include "LangInfo.h" #include "ServiceBroker.h" #include "URL.h" diff --git a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp index a5cb7989da..9c086dc109 100644 --- a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp @@ -9,6 +9,7 @@ #include "GUIDialogVideoBookmarks.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "TextureCache.h" #include "Util.h" diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp index 59daa631de..2585679c6e 100644 --- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp @@ -10,6 +10,7 @@ #include "ContextMenuManager.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" @@ -51,6 +52,7 @@ #include "utils/URIUtils.h" #include "utils/Variant.h" #include "video/VideoDbUrl.h" +#include "video/VideoFileItemClassify.h" #include "video/VideoInfoScanner.h" #include "video/VideoInfoTag.h" #include "video/VideoItemArtworkHandler.h" @@ -71,6 +73,7 @@ using namespace XFILE::VIDEODATABASEDIRECTORY; using namespace XFILE; using namespace KODI::MESSAGING; +using namespace KODI::VIDEO; #define CONTROL_IMAGE 3 #define CONTROL_TEXTAREA 4 @@ -279,7 +282,7 @@ void CGUIDialogVideoInfo::OnInitWindow() CONTROL_DISABLE(CONTROL_BTN_REFRESH); // @todo add support to edit video asset art. Until then edit art through Versions Manager. - if (!VIDEO::IsVideoAssetFile(*m_movieItem)) + if (!IsVideoAssetFile(*m_movieItem)) CONTROL_ENABLE_ON_CONDITION( CONTROL_BTN_GET_THUMB, (profileManager->GetCurrentProfile().canWriteDatabases() || @@ -1067,7 +1070,8 @@ std::string CGUIDialogVideoInfo::GetThumbnail() const int CGUIDialogVideoInfo::ManageVideoItem(const std::shared_ptr<CFileItem>& item) { - if (item == nullptr || !item->IsVideoDb() || !item->HasVideoInfoTag() || item->GetVideoInfoTag()->m_iDbId < 0) + if (item == nullptr || !IsVideoDb(*item) || !item->HasVideoInfoTag() || + item->GetVideoInfoTag()->m_iDbId < 0) return -1; CVideoDatabase database; @@ -1078,18 +1082,18 @@ int CGUIDialogVideoInfo::ManageVideoItem(const std::shared_ptr<CFileItem>& item) int dbId = item->GetVideoInfoTag()->m_iDbId; CContextButtons buttons; - if ((type == MediaTypeMovie && !VIDEO::IsVideoAssetFile(*item)) || - type == MediaTypeVideoCollection || type == MediaTypeTvShow || type == MediaTypeEpisode || + if ((type == MediaTypeMovie && !IsVideoAssetFile(*item)) || type == MediaTypeVideoCollection || + type == MediaTypeTvShow || type == MediaTypeEpisode || (type == MediaTypeSeason && item->GetVideoInfoTag()->m_iSeason > 0) || // seasons without "all seasons" and "specials" type == MediaTypeMusicVideo) buttons.Add(CONTEXT_BUTTON_EDIT, 16105); - if ((type == MediaTypeMovie && !VIDEO::IsVideoAssetFile(*item)) || type == MediaTypeTvShow || + if ((type == MediaTypeMovie && !IsVideoAssetFile(*item)) || type == MediaTypeTvShow || type == MediaTypeSeason) buttons.Add(CONTEXT_BUTTON_EDIT_SORTTITLE, 16107); - if (type == MediaTypeMovie && !VIDEO::IsVideoAssetFile(*item)) + if (type == MediaTypeMovie && !IsVideoAssetFile(*item)) { // only show link/unlink if there are tvshows available if (database.HasContent(VideoDbContentType::TVSHOWS)) @@ -1113,9 +1117,8 @@ int CGUIDialogVideoInfo::ManageVideoItem(const std::shared_ptr<CFileItem>& item) item->GetVideoInfoTag()->m_iBookmarkId > 0) buttons.Add(CONTEXT_BUTTON_UNLINK_BOOKMARK, 20405); - if (type == MediaTypeVideoCollection || - (type == MediaTypeMovie && !VIDEO::IsVideoAssetFile(*item)) || type == MediaTypeTvShow || - type == MediaTypeSeason || type == MediaTypeEpisode) + if (type == MediaTypeVideoCollection || (type == MediaTypeMovie && !IsVideoAssetFile(*item)) || + type == MediaTypeTvShow || type == MediaTypeSeason || type == MediaTypeEpisode) buttons.Add(CONTEXT_BUTTON_SET_ART, 13511); // movie sets @@ -1139,7 +1142,7 @@ int CGUIDialogVideoInfo::ManageVideoItem(const std::shared_ptr<CFileItem>& item) } } - if (type != MediaTypeSeason && !VIDEO::IsVideoAssetFile(*item)) + if (type != MediaTypeSeason && !IsVideoAssetFile(*item)) { // Remove from library buttons.Add(CONTEXT_BUTTON_DELETE, 646); diff --git a/xbmc/video/dialogs/GUIDialogVideoManager.cpp b/xbmc/video/dialogs/GUIDialogVideoManager.cpp index f5dc78b271..18c6d90562 100644 --- a/xbmc/video/dialogs/GUIDialogVideoManager.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoManager.cpp @@ -9,6 +9,7 @@ #include "GUIDialogVideoManager.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "MediaSource.h" #include "ServiceBroker.h" diff --git a/xbmc/video/dialogs/GUIDialogVideoManagerExtras.cpp b/xbmc/video/dialogs/GUIDialogVideoManagerExtras.cpp index 28bae13d04..9f8206d44e 100644 --- a/xbmc/video/dialogs/GUIDialogVideoManagerExtras.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoManagerExtras.cpp @@ -9,6 +9,7 @@ #include "GUIDialogVideoManagerExtras.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" #include "URL.h" diff --git a/xbmc/video/dialogs/GUIDialogVideoManagerVersions.cpp b/xbmc/video/dialogs/GUIDialogVideoManagerVersions.cpp index f2dada7087..f48c61ee67 100644 --- a/xbmc/video/dialogs/GUIDialogVideoManagerVersions.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoManagerVersions.cpp @@ -9,6 +9,7 @@ #include "GUIDialogVideoManagerVersions.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" #include "URL.h" diff --git a/xbmc/video/guilib/VideoGUIUtils.cpp b/xbmc/video/guilib/VideoGUIUtils.cpp index 76eeb807d5..9cd5487828 100644 --- a/xbmc/video/guilib/VideoGUIUtils.cpp +++ b/xbmc/video/guilib/VideoGUIUtils.cpp @@ -9,6 +9,7 @@ #include "VideoGUIUtils.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "PartyModeManager.h" #include "PlayListPlayer.h" @@ -200,7 +201,7 @@ void CAsyncGetItemsForPlaylist::GetItemsForPlaylist(const std::shared_ptr<CFileI items.Sort(sortDesc); } - if (items.GetContent().empty() && !items.IsVideoDb() && !items.IsVirtualDirectoryRoot() && + if (items.GetContent().empty() && !IsVideoDb(items) && !items.IsVirtualDirectoryRoot() && !items.IsSourcesPath() && !items.IsLibraryFolder()) { CVideoDatabase db; @@ -302,7 +303,7 @@ void CAsyncGetItemsForPlaylist::GetItemsForPlaylist(const std::shared_ptr<CFileI // a playable python files m_queuedItems.Add(item); } - else if (item->IsVideoDb()) + else if (IsVideoDb(*item)) { // this case is needed unless we allow IsVideo() to return true for videodb items, // but then we have issues with playlists of videodb items @@ -556,7 +557,7 @@ bool IsItemPlayable(const CFileItem& item) return false; if (item.m_bIsFolder && - (item.IsVideoDb() || StringUtils::StartsWithNoCase(item.GetPath(), "library://video/"))) + (IsVideoDb(item) || StringUtils::StartsWithNoCase(item.GetPath(), "library://video/"))) { // Exclude top level nodes - eg can't play 'genres' just a specific genre etc const XFILE::VIDEODATABASEDIRECTORY::NODE_TYPE node = diff --git a/xbmc/video/guilib/VideoSelectActionProcessor.cpp b/xbmc/video/guilib/VideoSelectActionProcessor.cpp index 665b55858d..b3a84b1fb8 100644 --- a/xbmc/video/guilib/VideoSelectActionProcessor.cpp +++ b/xbmc/video/guilib/VideoSelectActionProcessor.cpp @@ -9,6 +9,7 @@ #include "VideoSelectActionProcessor.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "dialogs/GUIDialogContextMenu.h" #include "dialogs/GUIDialogSelect.h" diff --git a/xbmc/video/guilib/VideoVersionHelper.cpp b/xbmc/video/guilib/VideoVersionHelper.cpp index e6ece8f03c..6a4923052b 100644 --- a/xbmc/video/guilib/VideoVersionHelper.cpp +++ b/xbmc/video/guilib/VideoVersionHelper.cpp @@ -9,6 +9,7 @@ #include "VideoVersionHelper.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "URL.h" #include "dialogs/GUIDialogSelect.h" @@ -21,9 +22,11 @@ #include "utils/StringUtils.h" #include "utils/log.h" #include "video/VideoDatabase.h" +#include "video/VideoFileItemClassify.h" #include "video/VideoManagerTypes.h" #include "video/VideoThumbLoader.h" +using namespace KODI::VIDEO; using namespace VIDEO::GUILIB; namespace @@ -278,17 +281,3 @@ std::shared_ptr<CFileItem> CVideoVersionHelper::ChooseVideoFromAssets( return item; } - -bool VIDEO::IsVideoAssetFile(const CFileItem& item) -{ - if (item.m_bIsFolder || !item.IsVideoDb()) - return false; - - // @todo maybe in the future look for prefix videodb://movies/videoversions in path instead - // @todo better encoding of video assets as path, they won't always be tied with movies. - const CURL itemUrl{item.GetPath()}; - if (itemUrl.HasOption("videoversionid")) - return true; - - return false; -} diff --git a/xbmc/video/guilib/VideoVersionHelper.h b/xbmc/video/guilib/VideoVersionHelper.h index 8d81ec1b65..b3ab15e503 100644 --- a/xbmc/video/guilib/VideoVersionHelper.h +++ b/xbmc/video/guilib/VideoVersionHelper.h @@ -23,11 +23,4 @@ public: }; } // namespace GUILIB -/*! - * \brief Is the item a video asset, excluding folders - * \param[in] item the item - * \return true if it is, false otherwise - */ -bool IsVideoAssetFile(const CFileItem& item); - } // namespace VIDEO diff --git a/xbmc/video/jobs/VideoLibraryMarkWatchedJob.cpp b/xbmc/video/jobs/VideoLibraryMarkWatchedJob.cpp index 486bd7a727..ef2e9253ad 100644 --- a/xbmc/video/jobs/VideoLibraryMarkWatchedJob.cpp +++ b/xbmc/video/jobs/VideoLibraryMarkWatchedJob.cpp @@ -9,6 +9,7 @@ #include "VideoLibraryMarkWatchedJob.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "Util.h" #include "filesystem/Directory.h" diff --git a/xbmc/video/jobs/VideoLibraryRefreshingJob.cpp b/xbmc/video/jobs/VideoLibraryRefreshingJob.cpp index 832bdd6b7f..ff0f7426fa 100644 --- a/xbmc/video/jobs/VideoLibraryRefreshingJob.cpp +++ b/xbmc/video/jobs/VideoLibraryRefreshingJob.cpp @@ -9,6 +9,7 @@ #include "VideoLibraryRefreshingJob.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "TextureDatabase.h" #include "URL.h" diff --git a/xbmc/video/jobs/VideoLibraryResetResumePointJob.cpp b/xbmc/video/jobs/VideoLibraryResetResumePointJob.cpp index 15b71a2955..1c9d2c768d 100644 --- a/xbmc/video/jobs/VideoLibraryResetResumePointJob.cpp +++ b/xbmc/video/jobs/VideoLibraryResetResumePointJob.cpp @@ -8,12 +8,13 @@ #include "VideoLibraryResetResumePointJob.h" -#include <vector> - #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "Util.h" #include "filesystem/IDirectory.h" + +#include <vector> #ifdef HAS_UPNP #include "network/upnp/UPnP.h" #endif diff --git a/xbmc/video/tags/VideoTagLoaderNFO.cpp b/xbmc/video/tags/VideoTagLoaderNFO.cpp index f85ce39818..c5e3b84539 100644 --- a/xbmc/video/tags/VideoTagLoaderNFO.cpp +++ b/xbmc/video/tags/VideoTagLoaderNFO.cpp @@ -9,6 +9,7 @@ #include "VideoTagLoaderNFO.h" #include "FileItem.h" +#include "FileItemList.h" #include "NfoFile.h" #include "URL.h" #include "filesystem/Directory.h" diff --git a/xbmc/video/tags/VideoTagLoaderPlugin.cpp b/xbmc/video/tags/VideoTagLoaderPlugin.cpp index f3b97ee608..6e7e8e0fbc 100644 --- a/xbmc/video/tags/VideoTagLoaderPlugin.cpp +++ b/xbmc/video/tags/VideoTagLoaderPlugin.cpp @@ -9,6 +9,7 @@ #include "VideoTagLoaderPlugin.h" #include "FileItem.h" +#include "FileItemList.h" #include "URL.h" #include "filesystem/PluginDirectory.h" diff --git a/xbmc/video/test/TestStacks.cpp b/xbmc/video/test/TestStacks.cpp index f5d92eabf8..12639a1a5f 100644 --- a/xbmc/video/test/TestStacks.cpp +++ b/xbmc/video/test/TestStacks.cpp @@ -7,6 +7,7 @@ */ #include "FileItem.h" +#include "FileItemList.h" #include "filesystem/Directory.h" #include "test/TestUtils.h" diff --git a/xbmc/video/test/TestVideoFileItemClassify.cpp b/xbmc/video/test/TestVideoFileItemClassify.cpp index 5824bec21a..3fae8d23a0 100644 --- a/xbmc/video/test/TestVideoFileItemClassify.cpp +++ b/xbmc/video/test/TestVideoFileItemClassify.cpp @@ -8,10 +8,15 @@ #include "FileItem.h" #include "ServiceBroker.h" +#include "filesystem/Directory.h" +#include "filesystem/File.h" #include "games/tags/GameInfoTag.h" #include "music/tags/MusicInfoTag.h" #include "pictures/PictureInfoTag.h" +#include "test/TestUtils.h" #include "utils/FileExtensionProvider.h" +#include "utils/FileUtils.h" +#include "utils/URIUtils.h" #include "video/VideoFileItemClassify.h" #include "video/VideoInfoTag.h" @@ -21,6 +26,47 @@ using namespace KODI; +struct StubDefinition +{ + StubDefinition(const std::string& path, + bool res = true, + const std::string& tagPath = "", + bool isFolder = false) + : item(path, isFolder), result(res) + { + if (!tagPath.empty()) + { + if (isFolder) + item.GetVideoInfoTag()->m_strPath = tagPath; + else + item.GetVideoInfoTag()->m_strFileNameAndPath = tagPath; + } + } + + CFileItem item; + bool result; +}; + +class DiscStubTest : public testing::WithParamInterface<StubDefinition>, public testing::Test +{ +}; + +TEST_P(DiscStubTest, IsDiscStub) +{ + EXPECT_EQ(VIDEO::IsDiscStub(GetParam().item), GetParam().result); +} + +const auto discstub_tests = std::array{ + StubDefinition{"/home/user/test.disc"}, + StubDefinition{"videodb://foo/bar", true, "/home/user/test.disc"}, + StubDefinition{"videodb://foo/bar", false, "/home/user/test.disc", true}, + StubDefinition{"/home/user/test.avi", false}, +}; + +INSTANTIATE_TEST_SUITE_P(TestVideoFileItemClassify, + DiscStubTest, + testing::ValuesIn(discstub_tests)); + struct VideoClassifyTest { VideoClassifyTest(const std::string& path, @@ -90,3 +136,84 @@ TEST(TestVideoFileItemClassify, VideoExtensions) EXPECT_TRUE(VIDEO::IsVideo(CFileItem(ext, false))); } } + +TEST(TestVideoFileItemClassify, IsBDFile) +{ + EXPECT_TRUE(VIDEO::IsBDFile(CFileItem("/home/foo/index.BDMV", false))); + EXPECT_TRUE(VIDEO::IsBDFile(CFileItem("smb://foo/bar/index.bdm", false))); + EXPECT_TRUE(VIDEO::IsBDFile(CFileItem("ftp://foo:bar@foobar.com/movieobject.BDMV", false))); + EXPECT_TRUE(VIDEO::IsBDFile(CFileItem("https://foobar.com/movieobj.bdm", false))); + EXPECT_FALSE(VIDEO::IsBDFile(CFileItem("https://foobar.com/movieobject.not", false))); +} + +TEST(TestVideoFileItemClassify, IsDVDFile) +{ + EXPECT_TRUE(VIDEO::IsDVDFile(CFileItem("/home/foo/video_ts.vob", false), true, false)); + EXPECT_TRUE(VIDEO::IsDVDFile(CFileItem("/home/foo/video_ts.VOB", false), true, true)); + EXPECT_FALSE(VIDEO::IsDVDFile(CFileItem("/home/foo/video_TS.vob", false), false, false)); + EXPECT_FALSE(VIDEO::IsDVDFile(CFileItem("/home/foo/video_ts.VOb", false), false, true)); + + EXPECT_TRUE(VIDEO::IsDVDFile(CFileItem("/home/foo/vts_yo_0.vob", false), true, false)); + EXPECT_TRUE(VIDEO::IsDVDFile(CFileItem("/home/foo/vts_0_ifo.vob", false), true, true)); + EXPECT_FALSE(VIDEO::IsDVDFile(CFileItem("/home/foo/VTS_123456_0.vob", false), false, false)); + EXPECT_FALSE(VIDEO::IsDVDFile(CFileItem("/home/foo/VTS_qwerty_0.VOB", false), false, true)); + + EXPECT_TRUE(VIDEO::IsDVDFile(CFileItem("/home/foo/video_ts.IFO", false), false, true)); + EXPECT_TRUE(VIDEO::IsDVDFile(CFileItem("/home/foo/video_ts.IFO", false), true, true)); + EXPECT_FALSE(VIDEO::IsDVDFile(CFileItem("/home/foo/video_ts.IFO", false), false, false)); + EXPECT_FALSE(VIDEO::IsDVDFile(CFileItem("/home/foo/video_ts.IFO", false), true, false)); + + EXPECT_TRUE(VIDEO::IsDVDFile(CFileItem("/home/foo/vts_ab_0.ifo", false), false, true)); + EXPECT_TRUE(VIDEO::IsDVDFile(CFileItem("/home/foo/vts_ab_0.ifo", false), false, true)); + EXPECT_FALSE(VIDEO::IsDVDFile(CFileItem("/home/foo/VTS_ab_0.ifo", false), false, false)); + EXPECT_FALSE(VIDEO::IsDVDFile(CFileItem("/home/foo/VTS_ab_0.ifo", false), false, false)); +} + +TEST(TestVideoFileItemClassify, IsProtectedBlurayDisc) +{ + const auto temp_file = CXBMCTestUtils::Instance().CreateTempFile("bluraytest"); + const std::string dir = CXBMCTestUtils::Instance().TempFileDirectory(temp_file); + CFileUtils::DeleteItem(URIUtils::AddFileToFolder(dir, "AACS", "Unit_Key_RO.inf")); + EXPECT_FALSE(VIDEO::IsProtectedBlurayDisc(CFileItem(dir, true))); + XFILE::CDirectory::Create(URIUtils::AddFileToFolder(dir, "AACS")); + XFILE::CFile inf_file; + inf_file.OpenForWrite(URIUtils::AddFileToFolder(dir, "AACS", "Unit_Key_RO.inf")); + inf_file.Close(); + EXPECT_TRUE(VIDEO::IsProtectedBlurayDisc(CFileItem(dir, true))); + CFileUtils::DeleteItem(URIUtils::AddFileToFolder(dir, "AACS", "Unit_Key_RO.inf")); + CXBMCTestUtils::Instance().DeleteTempFile(temp_file); +} + +TEST(TestVideoFileItemClassify, IsSubtitle) +{ + const auto& exts = CServiceBroker::GetFileExtensionProvider().GetSubtitleExtensions(); + for (const auto& ext : StringUtils::Split(exts, "|")) + { + if (!ext.empty()) + EXPECT_TRUE(VIDEO::IsSubtitle(CFileItem("random" + ext, false))); + } + + EXPECT_FALSE(VIDEO::IsSubtitle(CFileItem("random.notasub", false))); +} + +TEST(TestVideoFileItemClassify, IsVideoAssetsFile) +{ + EXPECT_TRUE(VIDEO::IsVideoAssetFile(CFileItem("videodb://foo/bar?videoversionid=1", false))); + EXPECT_FALSE(VIDEO::IsVideoAssetFile(CFileItem("videodb://foo/bar?videoversionid=1", true))); + EXPECT_FALSE(VIDEO::IsVideoAssetFile(CFileItem("videodb://foo/bar", false))); +} + +TEST(TestVideoFileItemClassify, IsVideoDb) +{ + EXPECT_TRUE(VIDEO::IsVideoDb(CFileItem("videodb://1/2/3", false))); + EXPECT_TRUE(VIDEO::IsVideoDb(CFileItem("videodb://1/2/", true))); + EXPECT_FALSE(VIDEO::IsVideoDb(CFileItem("/videodb/home/foo/Extraordinary/", true))); +} + +TEST(TestVideoFileItemClassify, IsVideoExtrasFolder) +{ + EXPECT_TRUE(VIDEO::IsVideoExtrasFolder(CFileItem("/home/foo/Extras/", true))); + EXPECT_TRUE(VIDEO::IsVideoExtrasFolder(CFileItem("/home/foo/extras/", true))); + EXPECT_FALSE(VIDEO::IsVideoExtrasFolder(CFileItem("/home/foo/Extraordinary/", true))); + EXPECT_FALSE(VIDEO::IsVideoExtrasFolder(CFileItem("/home/foo/Extras/abc.mkv", false))); +} diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp index 7d57d7f6e4..13c1bd25d2 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.cpp +++ b/xbmc/video/windows/GUIWindowVideoBase.cpp @@ -10,6 +10,7 @@ #include "Autorun.h" #include "ContextMenuManager.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "GUIUserMessages.h" #include "PartyModeManager.h" @@ -225,13 +226,13 @@ bool CGUIWindowVideoBase::OnItemInfo(const CFileItem& fileItem) return false; // Movie set - if (fileItem.m_bIsFolder && fileItem.IsVideoDb() && + if (fileItem.m_bIsFolder && IsVideoDb(fileItem) && fileItem.GetPath() != "videodb://movies/sets/" && StringUtils::StartsWith(fileItem.GetPath(), "videodb://movies/sets/")) return ShowInfoAndRefresh(std::make_shared<CFileItem>(fileItem), nullptr); // Music video. Match visibility test of CMusicInfo::IsVisible - if (fileItem.IsVideoDb() && fileItem.HasVideoInfoTag() && + if (IsVideoDb(fileItem) && fileItem.HasVideoInfoTag() && (fileItem.HasProperty("artist_musicid") || fileItem.HasProperty("album_musicid"))) { CGUIDialogMusicInfo::ShowFor(std::make_shared<CFileItem>(fileItem).get()); @@ -239,7 +240,7 @@ bool CGUIWindowVideoBase::OnItemInfo(const CFileItem& fileItem) } std::string strDir; - if (fileItem.IsVideoDb() && fileItem.HasVideoInfoTag() && + if (IsVideoDb(fileItem) && fileItem.HasVideoInfoTag() && !fileItem.GetVideoInfoTag()->m_strPath.empty()) strDir = fileItem.GetVideoInfoTag()->m_strPath; else @@ -270,7 +271,7 @@ bool CGUIWindowVideoBase::OnItemInfo(const CFileItem& fileItem) return true; CFileItem item(fileItem); - if ((item.IsVideoDb() && item.HasVideoInfoTag()) || + if ((IsVideoDb(item) && item.HasVideoInfoTag()) || (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_iDbId != -1)) { if (item.GetVideoInfoTag()->m_type == MediaTypeSeason) @@ -427,7 +428,7 @@ bool CGUIWindowVideoBase::ShowInfo(const CFileItemPtr& item2, const ScraperPtr& if (bHasInfo) { // @todo add support to refresh movie version information - if (!info || info->Content() == CONTENT_NONE || VIDEO::IsVideoAssetFile(*item)) + if (!info || info->Content() == CONTENT_NONE || IsVideoAssetFile(*item)) item->SetProperty("xxuniqueid", "xx" + movieDetails.GetUniqueID()); // disable refresh button item->SetProperty("CheckAutoPlayNextItem", IsActive()); *item->GetVideoInfoTag() = movieDetails; @@ -443,9 +444,9 @@ bool CGUIWindowVideoBase::ShowInfo(const CFileItemPtr& item2, const ScraperPtr& { item = pDlgInfo->GetCurrentListItem(); - if (item->IsVideoDb() && item->HasVideoInfoTag()) + if (IsVideoDb(*item) && item->HasVideoInfoTag()) item->SetPath(item->GetVideoInfoTag()->GetPath()); - else if (!item->IsVideoDb() && item->m_bIsFolder) + else if (!IsVideoDb(*item) && item->m_bIsFolder) { // Info on folder containing a movie needs dyn path as path for refresh with correct name //! @todo get rid of "videos with versions as folder" hack to be able to fix in CFileItem::GetBaseMoviePath() @@ -494,7 +495,7 @@ bool CGUIWindowVideoBase::ShowInfo(const CFileItemPtr& item2, const ScraperPtr& { item = pDlgInfo->GetCurrentListItem(); - if (item->IsVideoDb() && item->HasVideoInfoTag()) + if (IsVideoDb(*item) && item->HasVideoInfoTag()) item->SetPath(item->GetVideoInfoTag()->GetPath()); } listNeedsUpdating = true; @@ -802,7 +803,7 @@ void CGUIWindowVideoBase::GetContextButtons(int itemNumber, CContextButtons &but if (!item->IsParentFolder()) { std::string path(item->GetPath()); - if (item->IsVideoDb() && item->HasVideoInfoTag()) + if (IsVideoDb(*item) && item->HasVideoInfoTag()) path = item->GetVideoInfoTag()->m_strFileNameAndPath; if (!item->IsPath("add") && !item->IsPlugin() && @@ -913,13 +914,13 @@ bool CGUIWindowVideoBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button) if (!item) return false; - if (item->IsVideoDb() && (!item->m_bIsFolder || item->GetVideoInfoTag()->m_strPath.empty())) + if (IsVideoDb(*item) && (!item->m_bIsFolder || item->GetVideoInfoTag()->m_strPath.empty())) return false; if (item->m_bIsFolder) { const std::string strPath = - item->IsVideoDb() ? item->GetVideoInfoTag()->m_strPath : item->GetPath(); + IsVideoDb(*item) ? item->GetVideoInfoTag()->m_strPath : item->GetPath(); OnScan(strPath, true); } else @@ -969,7 +970,7 @@ bool CGUIWindowVideoBase::OnPlayMedia(const std::shared_ptr<CFileItem>& pItem, auto itemCopy = std::make_shared<CFileItem>(*pItem); - if (pItem->IsVideoDb()) + if (IsVideoDb(*pItem)) { itemCopy->SetPath(pItem->GetVideoInfoTag()->m_strFileNameAndPath); itemCopy->SetProperty("original_listitem_url", pItem->GetPath()); @@ -1082,7 +1083,7 @@ void CGUIWindowVideoBase::LoadPlayList(const std::string& strPlayList, bool CGUIWindowVideoBase::PlayItem(const std::shared_ptr<CFileItem>& pItem, const std::string& player) { - if (!pItem->m_bIsFolder && pItem->IsVideoDb() && !pItem->Exists()) + if (!pItem->m_bIsFolder && IsVideoDb(*pItem) && !pItem->Exists()) { CLog::LogF(LOGDEBUG, "File '{}' for library item '{}' doesn't exist.", pItem->GetDynPath(), pItem->GetPath()); @@ -1218,9 +1219,8 @@ bool CGUIWindowVideoBase::GetDirectory(const std::string &strDirectory, CFileIte bool CGUIWindowVideoBase::StackingAvailable(const CFileItemList &items) { CURL url(items.GetPath()); - return !(items.IsPlugin() || items.IsAddonsPath() || - items.IsRSS() || items.IsInternetStream() || - items.IsVideoDb() || url.IsProtocol("playlistvideo")); + return !(items.IsPlugin() || items.IsAddonsPath() || items.IsRSS() || items.IsInternetStream() || + IsVideoDb(items) || url.IsProtocol("playlistvideo")); } void CGUIWindowVideoBase::GetGroupedItems(CFileItemList &items) @@ -1267,9 +1267,9 @@ void CGUIWindowVideoBase::GetGroupedItems(CFileItemList &items) bool CGUIWindowVideoBase::CheckFilterAdvanced(CFileItemList &items) const { const std::string& content = items.GetContent(); - if ((items.IsVideoDb() || CanContainFilter(m_strFilterPath)) && - (StringUtils::EqualsNoCase(content, "movies") || - StringUtils::EqualsNoCase(content, "tvshows") || + if ((IsVideoDb(items) || CanContainFilter(m_strFilterPath)) && + (StringUtils::EqualsNoCase(content, "movies") || + StringUtils::EqualsNoCase(content, "tvshows") || StringUtils::EqualsNoCase(content, "episodes") || StringUtils::EqualsNoCase(content, "musicvideos"))) return true; @@ -1343,7 +1343,8 @@ void CGUIWindowVideoBase::OnSearchItemFound(const CFileItem* pSelItem) Update(strParentPath); - if (pSelItem->IsVideoDb() && CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MYVIDEOS_FLATTEN)) + if (IsVideoDb(*pSelItem) && CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( + CSettings::SETTING_MYVIDEOS_FLATTEN)) SetHistoryForPath(""); else SetHistoryForPath(strParentPath); @@ -1369,7 +1370,8 @@ void CGUIWindowVideoBase::OnSearchItemFound(const CFileItem* pSelItem) Update(strPath); - if (pSelItem->IsVideoDb() && CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MYVIDEOS_FLATTEN)) + if (IsVideoDb(*pSelItem) && CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( + CSettings::SETTING_MYVIDEOS_FLATTEN)) SetHistoryForPath(""); else SetHistoryForPath(strPath); @@ -1378,7 +1380,7 @@ void CGUIWindowVideoBase::OnSearchItemFound(const CFileItem* pSelItem) { CFileItemPtr pItem = m_vecItems->Get(i); CURL url(pItem->GetPath()); - if (pSelItem->IsVideoDb()) + if (IsVideoDb(*pSelItem)) url.SetOptions(""); if (url.Get() == pSelItem->GetPath()) { @@ -1520,7 +1522,7 @@ void CGUIWindowVideoBase::UpdateVideoVersionItems() //! not for example for home screen widgets! int videoVersionId{-1}; - if (item->IsVideoDb() && item->GetVideoInfoTag()->HasVideoVersions()) + if (IsVideoDb(*item) && item->GetVideoInfoTag()->HasVideoVersions()) { if (item->GetProperty("has_resolved_video_asset").asBoolean(false)) { diff --git a/xbmc/video/windows/GUIWindowVideoNav.cpp b/xbmc/video/windows/GUIWindowVideoNav.cpp index 86ab1d96eb..69b81a760a 100644 --- a/xbmc/video/windows/GUIWindowVideoNav.cpp +++ b/xbmc/video/windows/GUIWindowVideoNav.cpp @@ -9,6 +9,7 @@ #include "GUIWindowVideoNav.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "PartyModeManager.h" #include "ServiceBroker.h" @@ -39,6 +40,7 @@ #include "utils/Variant.h" #include "utils/log.h" #include "video/VideoDbUrl.h" +#include "video/VideoFileItemClassify.h" #include "video/VideoInfoScanner.h" #include "video/VideoLibraryQueue.h" #include "video/dialogs/GUIDialogVideoInfo.h" @@ -49,6 +51,7 @@ using namespace XFILE; using namespace VIDEODATABASEDIRECTORY; using namespace KODI::MESSAGING; +using namespace KODI::VIDEO; #define CONTROL_BTNVIEWASICONS 2 #define CONTROL_BTNSORTBY 3 @@ -152,7 +155,7 @@ bool CGUIWindowVideoNav::OnMessage(CGUIMessage& message) // We are here if the item is filtered out in the nav window const std::string& path = message.GetStringParam(0); CFileItem item(path, URIUtils::HasSlashAtEnd(path)); - if (item.IsVideoDb()) + if (IsVideoDb(item)) { *(item.GetVideoInfoTag()) = XFILE::CVideoDatabaseFile::GetVideoTag(CURL(item.GetPath())); if (!item.GetVideoInfoTag()->IsEmpty()) @@ -242,7 +245,7 @@ bool CGUIWindowVideoNav::OnMessage(CGUIMessage& message) SelectFirstUnwatchedItem CGUIWindowVideoNav::GetSettingSelectFirstUnwatchedItem() { - if (m_vecItems->IsVideoDb()) + if (IsVideoDb(*m_vecItems)) { NODE_TYPE nodeType = CVideoDatabaseDirectory::GetDirectoryChildType(m_vecItems->GetPath()); @@ -358,7 +361,7 @@ bool CGUIWindowVideoNav::GetDirectory(const std::string &strDirectory, CFileItem bool bResult = CGUIWindowVideoBase::GetDirectory(strDirectory, items); if (bResult) { - if (items.IsVideoDb()) + if (IsVideoDb(items)) { XFILE::CVideoDatabaseDirectory dir; CQueryParams params; @@ -546,7 +549,7 @@ void CGUIWindowVideoNav::UpdateButtons() else if (m_vecItems->IsPath("sources://video/")) strLabel = g_localizeStrings.Get(744); // everything else is from a videodb:// path - else if (m_vecItems->IsVideoDb()) + else if (IsVideoDb(*m_vecItems)) { CVideoDatabaseDirectory dir; dir.GetLabel(m_vecItems->GetPath(), strLabel); @@ -671,7 +674,7 @@ void CGUIWindowVideoNav::OnDeleteItem(const CFileItemPtr& pItem) if (m_vecItems->IsParentFolder()) return; - if (!m_vecItems->IsVideoDb() && !pItem->IsVideoDb()) + if (!IsVideoDb(*m_vecItems) && !IsVideoDb(*pItem)) { if (!pItem->IsPath("newsmartplaylist://video") && !pItem->IsPath("special://videoplaylists/") && !pItem->IsPath("sources://video/") && !URIUtils::IsProtocol(pItem->GetPath(), "newtag")) @@ -798,7 +801,7 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt // can we update the database? if (profileManager->GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) { - if (!CVideoLibraryQueue::GetInstance().IsScanningLibrary() && item->IsVideoDb() && + if (!CVideoLibraryQueue::GetInstance().IsScanningLibrary() && IsVideoDb(*item) && item->HasVideoInfoTag() && (item->GetVideoInfoTag()->m_type == MediaTypeMovie || // movies item->GetVideoInfoTag()->m_type == MediaTypeTvShow || // tvshows @@ -824,7 +827,7 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt } } - if (!m_vecItems->IsVideoDb() && !m_vecItems->IsVirtualDirectoryRoot()) + if (!IsVideoDb(*m_vecItems) && !m_vecItems->IsVirtualDirectoryRoot()) { // non-video db items, file operations are allowed if ((CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_FILELISTS_ALLOWFILEDELETION) && CUtil::SupportsWriteFileOperations(item->GetPath())) || @@ -835,7 +838,9 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt buttons.Add(CONTEXT_BUTTON_RENAME, 118); } // add "Set/Change content" to folders - if (item->m_bIsFolder && !item->IsVideoDb() && !item->IsPlayList() && !item->IsSmartPlayList() && !item->IsLibraryFolder() && !item->IsLiveTV() && !item->IsPlugin() && !item->IsAddonsPath() && !URIUtils::IsUPnP(item->GetPath())) + if (item->m_bIsFolder && !IsVideoDb(*item) && !item->IsPlayList() && + !item->IsSmartPlayList() && !item->IsLibraryFolder() && !item->IsLiveTV() && + !item->IsPlugin() && !item->IsAddonsPath() && !URIUtils::IsUPnP(item->GetPath())) { if (info && info->Content() != CONTENT_NONE) buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20442); @@ -1079,7 +1084,7 @@ bool CGUIWindowVideoNav::ApplyWatchedFilter(CFileItemList &items) || node == NODE_TYPE_RECENTLY_ADDED_MOVIES || node == NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS) filterWatched = true; - if (!items.IsVideoDb()) + if (!IsVideoDb(items)) filterWatched = true; if (items.GetContent() == "tvshows" && (items.IsSmartPlayList() || items.IsLibraryFolder())) diff --git a/xbmc/video/windows/GUIWindowVideoPlaylist.cpp b/xbmc/video/windows/GUIWindowVideoPlaylist.cpp index 3569a0c5ea..bb381a9dbc 100644 --- a/xbmc/video/windows/GUIWindowVideoPlaylist.cpp +++ b/xbmc/video/windows/GUIWindowVideoPlaylist.cpp @@ -8,6 +8,7 @@ #include "GUIWindowVideoPlaylist.h" +#include "FileItemList.h" #include "GUIUserMessages.h" #include "PartyModeManager.h" #include "PlayListPlayer.h" @@ -30,6 +31,7 @@ #include "utils/URIUtils.h" #include "utils/Variant.h" #include "utils/log.h" +#include "video/VideoFileItemClassify.h" #include "video/guilib/VideoPlayActionProcessor.h" #define CONTROL_BTNVIEWASICONS 2 @@ -46,6 +48,7 @@ #define CONTROL_BTNPREVIOUS 25 #define CONTROL_BTNREPEAT 26 +using namespace KODI::VIDEO; using namespace VIDEO::GUILIB; CGUIWindowVideoPlaylist::CGUIWindowVideoPlaylist() @@ -63,7 +66,7 @@ void CGUIWindowVideoPlaylist::OnPrepareFileItems(CFileItemList& items) if (items.IsEmpty()) return; - if (!items.IsVideoDb() && !items.IsVirtualDirectoryRoot()) + if (!IsVideoDb(items) && !items.IsVirtualDirectoryRoot()) { // load info from the database std::string label; if (items.GetLabel().empty() && diff --git a/xbmc/video/windows/VideoFileItemListModifier.cpp b/xbmc/video/windows/VideoFileItemListModifier.cpp index b17a71db87..2f5c222c62 100644 --- a/xbmc/video/windows/VideoFileItemListModifier.cpp +++ b/xbmc/video/windows/VideoFileItemListModifier.cpp @@ -9,6 +9,7 @@ #include "VideoFileItemListModifier.h" #include "FileItem.h" +#include "FileItemList.h" #include "ServiceBroker.h" #include "filesystem/VideoDatabaseDirectory/DirectoryNode.h" #include "guilib/LocalizeStrings.h" @@ -17,14 +18,16 @@ #include "settings/SettingsComponent.h" #include "video/VideoDatabase.h" #include "video/VideoDbUrl.h" +#include "video/VideoFileItemClassify.h" #include <memory> +using namespace KODI::VIDEO; using namespace XFILE::VIDEODATABASEDIRECTORY; bool CVideoFileItemListModifier::CanModify(const CFileItemList &items) const { - if (items.IsVideoDb()) + if (IsVideoDb(items)) return true; return false; @@ -40,7 +43,7 @@ bool CVideoFileItemListModifier::Modify(CFileItemList &items) const // depending on the child node void CVideoFileItemListModifier::AddQueuingFolder(CFileItemList& items) { - if (!items.IsVideoDb()) + if (!IsVideoDb(items)) return; auto directoryNode = CDirectoryNode::ParseURL(items.GetPath()); diff --git a/xbmc/view/GUIViewControl.cpp b/xbmc/view/GUIViewControl.cpp index 3d4801b693..6ce4516b52 100644 --- a/xbmc/view/GUIViewControl.cpp +++ b/xbmc/view/GUIViewControl.cpp @@ -9,6 +9,7 @@ #include "GUIViewControl.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIInfoManager.h" #include "ServiceBroker.h" #include "guilib/GUIComponent.h" diff --git a/xbmc/view/GUIViewState.cpp b/xbmc/view/GUIViewState.cpp index e0cf9d2aca..89c234a709 100644 --- a/xbmc/view/GUIViewState.cpp +++ b/xbmc/view/GUIViewState.cpp @@ -10,6 +10,7 @@ #include "AutoSwitch.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "PlayListPlayer.h" #include "ServiceBroker.h" diff --git a/xbmc/windowing/osx/OpenGL/OSXGLView.h b/xbmc/windowing/osx/OpenGL/OSXGLView.h index 54a85a232f..016e102e78 100644 --- a/xbmc/windowing/osx/OpenGL/OSXGLView.h +++ b/xbmc/windowing/osx/OpenGL/OSXGLView.h @@ -16,12 +16,6 @@ - (CGLContextObj)getGLContextObj; /** - * @brief Application renders out of the NSOpenGLView drawRect (on a different thread). Hence the current - * NSOpenGLContext needs to be make current so that the view on the context is valid for rendering. - * This should be done whenever gl calls are about to be done. - */ -- (void)NotifyContext; -/** * @brief Update the current OpenGL context (view is set before updating) */ - (void)Update; @@ -30,9 +24,4 @@ */ - (void)FlushBuffer; -/** - * @brief Specifies if the glContext is currently owned by the view - */ -@property(atomic, assign) BOOL glContextOwned; - @end diff --git a/xbmc/windowing/osx/OpenGL/OSXGLView.mm b/xbmc/windowing/osx/OpenGL/OSXGLView.mm index 195ea0d889..857174838a 100644 --- a/xbmc/windowing/osx/OpenGL/OSXGLView.mm +++ b/xbmc/windowing/osx/OpenGL/OSXGLView.mm @@ -20,8 +20,6 @@ NSTrackingArea* m_trackingArea; } -@synthesize glContextOwned; - - (void)SendInputEvent:(NSEvent*)nsEvent { CWinSystemOSX* winSystem = dynamic_cast<CWinSystemOSX*>(CServiceBroker::GetWinSystem()); @@ -88,14 +86,6 @@ - (void)drawRect:(NSRect)rect { - // whenever the view/window is resized the glContext is made current to the main (rendering) thread. - // Since kodi does its rendering on the application main thread (not the macOS rendering thread), we - // need to store this so that on a subsquent frame render we get the ownership of the gl context again. - // doing this blindly without any sort of control may stall the main thread and lead to low GUI fps - // since the glContext ownership needs to be obtained from the rendering thread (diverged from the actual - // thread doing the rendering calls). - [self setGlContextOwned:TRUE]; - static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [self setOpenGLContext:m_glcontext]; @@ -215,17 +205,8 @@ - (void)Update { assert(m_glcontext); - [self NotifyContext]; - [m_glcontext update]; -} - -- (void)NotifyContext -{ - assert(m_glcontext); - // signals/notifies the context that this view is current (required if we render out of DrawRect) - // ownership of the context is transferred to the callee thread [m_glcontext makeCurrentContext]; - [self setGlContextOwned:FALSE]; + [m_glcontext update]; } - (void)FlushBuffer diff --git a/xbmc/windowing/osx/OpenGL/WindowControllerMacOS.mm b/xbmc/windowing/osx/OpenGL/WindowControllerMacOS.mm index 5bfb6b0d22..4f50a49dbc 100644 --- a/xbmc/windowing/osx/OpenGL/WindowControllerMacOS.mm +++ b/xbmc/windowing/osx/OpenGL/WindowControllerMacOS.mm @@ -22,6 +22,8 @@ @implementation XBMCWindowControllerMacOS +bool m_inFullscreenTransition = false; + - (nullable instancetype)initWithTitle:(NSString*)title defaultSize:(NSSize)size { auto frame = NSMakeRect(0, 0, size.width, size.height); @@ -77,6 +79,30 @@ } } +- (void)windowWillStartLiveResize:(NSNotification*)notification +{ + if (m_inFullscreenTransition) + return; + + std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort(); + if (appPort) + { + appPort->SetRenderGUI(false); + } +} + +- (void)windowDidEndLiveResize:(NSNotification*)notification +{ + if (m_inFullscreenTransition) + return; + + std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort(); + if (appPort) + { + appPort->SetRenderGUI(true); + } +} + - (void)windowDidMiniaturize:(NSNotification*)aNotification { g_application.m_AppFocused = false; @@ -170,8 +196,14 @@ return frameSize; } +- (void)windowWillExitFullScreen:(NSNotification*)notification +{ + m_inFullscreenTransition = true; +} + - (void)windowWillEnterFullScreen:(NSNotification*)pNotification { + m_inFullscreenTransition = true; CWinSystemOSX* winSystem = dynamic_cast<CWinSystemOSX*>(CServiceBroker::GetWinSystem()); if (!winSystem) return; @@ -209,6 +241,7 @@ - (void)windowDidExitFullScreen:(NSNotification*)pNotification { + m_inFullscreenTransition = false; auto winSystem = dynamic_cast<CWinSystemOSX*>(CServiceBroker::GetWinSystem()); if (!winSystem) return; @@ -235,6 +268,7 @@ - (void)windowDidEnterFullScreen:(NSNotification*)notification { + m_inFullscreenTransition = false; auto winSystem = dynamic_cast<CWinSystemOSX*>(CServiceBroker::GetWinSystem()); if (!winSystem) return; diff --git a/xbmc/windowing/osx/WinSystemOSX.h b/xbmc/windowing/osx/WinSystemOSX.h index c431d70cd9..899e52486b 100644 --- a/xbmc/windowing/osx/WinSystemOSX.h +++ b/xbmc/windowing/osx/WinSystemOSX.h @@ -71,7 +71,6 @@ public: void MoveToScreen(unsigned int screenIdx) override; void OnMove(int x, int y) override; void OnChangeScreen(unsigned int screenIdx) override; - CGraphicContext& GetGfxContext() const override; bool HasValidResolution() const; std::string GetClipboardText() override; diff --git a/xbmc/windowing/osx/WinSystemOSX.mm b/xbmc/windowing/osx/WinSystemOSX.mm index 04a0670a17..007fc14be3 100644 --- a/xbmc/windowing/osx/WinSystemOSX.mm +++ b/xbmc/windowing/osx/WinSystemOSX.mm @@ -1304,18 +1304,6 @@ CGLContextObj CWinSystemOSX::GetCGLContextObj() return cglcontex; } -CGraphicContext& CWinSystemOSX::GetGfxContext() const -{ - if (m_glView && [m_glView glContextOwned]) - { - dispatch_sync(dispatch_get_main_queue(), ^{ - [m_glView NotifyContext]; - }); - } - - return CWinSystemBase::GetGfxContext(); -} - bool CWinSystemOSX::FlushBuffer() { if (m_appWindow) diff --git a/xbmc/windowing/win10/WinSystemWin10.cpp b/xbmc/windowing/win10/WinSystemWin10.cpp index ccdbc395f3..1461d797b0 100644 --- a/xbmc/windowing/win10/WinSystemWin10.cpp +++ b/xbmc/windowing/win10/WinSystemWin10.cpp @@ -692,7 +692,14 @@ float CWinSystemWin10::GetGuiSdrPeakLuminance() const */ bool CWinSystemWin10::HasSystemSdrPeakLuminance() { - return CWIN32Util::GetSystemSdrWhiteLevel(std::wstring(), nullptr); + if (m_uiThreadId == GetCurrentThreadId()) + { + const bool hasSystemSdrPeakLum = CWIN32Util::GetSystemSdrWhiteLevel(std::wstring(), nullptr); + m_cachedHasSystemSdrPeakLum = hasSystemSdrPeakLum; + return hasSystemSdrPeakLum; + } + + return m_cachedHasSystemSdrPeakLum; } /*! diff --git a/xbmc/windowing/win10/WinSystemWin10.h b/xbmc/windowing/win10/WinSystemWin10.h index c53fd01872..6b5be4bb4e 100644 --- a/xbmc/windowing/win10/WinSystemWin10.h +++ b/xbmc/windowing/win10/WinSystemWin10.h @@ -156,6 +156,10 @@ protected: bool m_validSystemSdrPeakLuminance{false}; float m_systemSdrPeakLuminance{.0f}; + + DWORD m_uiThreadId{0}; + HDR_STATUS m_cachedHdrStatus{HDR_STATUS::HDR_UNSUPPORTED}; + bool m_cachedHasSystemSdrPeakLum{false}; }; #pragma pack(pop) diff --git a/xbmc/windowing/win10/WinSystemWin10DX.cpp b/xbmc/windowing/win10/WinSystemWin10DX.cpp index 1101b1a7ef..55167ff386 100644 --- a/xbmc/windowing/win10/WinSystemWin10DX.cpp +++ b/xbmc/windowing/win10/WinSystemWin10DX.cpp @@ -61,6 +61,14 @@ bool CWinSystemWin10DX::CreateNewWindow(const std::string& name, bool fullScreen m_deviceResources = DX::DeviceResources::Get(); m_deviceResources->SetWindow(m_coreWindow); + // saves threadId of current thread (UI thread) + m_uiThreadId = GetCurrentThreadId(); + + // calls these methods to make sure cached values are properly initialized + // and can be used later when called from other thread + IsHDRDisplay(); + HasSystemSdrPeakLuminance(); + if (CWinSystemWin10::CreateNewWindow(name, fullScreen, res) && m_deviceResources->HasValidDevice()) { CGenericTouchInputHandler::GetInstance().RegisterHandler(&CGenericTouchActionHandler::GetInstance()); @@ -166,7 +174,14 @@ void CWinSystemWin10DX::InitHooks(IDXGIOutput* pOutput) bool CWinSystemWin10DX::IsHDRDisplay() { - return (CWIN32Util::GetWindowsHDRStatus() != HDR_STATUS::HDR_UNSUPPORTED); + if (m_uiThreadId == GetCurrentThreadId()) + { + const HDR_STATUS hdrStatus = CWIN32Util::GetWindowsHDRStatus(); + m_cachedHdrStatus = hdrStatus; + return (hdrStatus != HDR_STATUS::HDR_UNSUPPORTED); + } + + return (m_cachedHdrStatus != HDR_STATUS::HDR_UNSUPPORTED); } HDR_STATUS CWinSystemWin10DX::GetOSHDRStatus() diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp index 5dacf417a1..aab1d37e0c 100644 --- a/xbmc/windows/GUIMediaWindow.cpp +++ b/xbmc/windows/GUIMediaWindow.cpp @@ -10,6 +10,7 @@ #include "ContextMenuManager.h" #include "FileItem.h" +#include "FileItemList.h" #include "FileItemListModification.h" #include "GUIPassword.h" #include "GUIUserMessages.h" @@ -59,6 +60,7 @@ #include "utils/URIUtils.h" #include "utils/Variant.h" #include "utils/log.h" +#include "video/VideoFileItemClassify.h" #include "view/GUIViewState.h" #include <inttypes.h> @@ -78,6 +80,7 @@ using namespace ADDON; using namespace KODI::MESSAGING; +using namespace KODI::VIDEO; using namespace std::chrono_literals; namespace @@ -1550,7 +1553,8 @@ bool CGUIMediaWindow::OnPlayAndQueueMedia(const CFileItemPtr& item, const std::s if (nItem->m_bIsFolder) continue; - if (!nItem->IsZIP() && !nItem->IsRAR() && (!nItem->IsDVDFile() || (URIUtils::GetFileName(nItem->GetDynPath()) == mainDVD))) + if (!nItem->IsZIP() && !nItem->IsRAR() && + (!IsDVDFile(*nItem) || (URIUtils::GetFileName(nItem->GetDynPath()) == mainDVD))) CServiceBroker::GetPlaylistPlayer().Add(playlistId, nItem); if (item->IsSamePath(nItem.get())) diff --git a/xbmc/windows/GUIWindowLoginScreen.cpp b/xbmc/windows/GUIWindowLoginScreen.cpp index 04eb5f9041..c95f6e4b61 100644 --- a/xbmc/windows/GUIWindowLoginScreen.cpp +++ b/xbmc/windows/GUIWindowLoginScreen.cpp @@ -9,6 +9,7 @@ #include "GUIWindowLoginScreen.h" #include "FileItem.h" +#include "FileItemList.h" #include "GUIPassword.h" #include "ServiceBroker.h" #include "addons/Skin.h" |