aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/resource.language.en_gb/resources/strings.po22
-rw-r--r--cmake/modules/FindFFMPEG.cmake5
-rw-r--r--cmake/modules/FindFlatBuffers.cmake42
-rw-r--r--cmake/modules/FindNFS.cmake8
-rw-r--r--cmake/modules/FindPCRE.cmake5
-rw-r--r--cmake/modules/FindTagLib.cmake4
-rw-r--r--cmake/modules/buildtools/FindFlatC.cmake25
-rw-r--r--cmake/modules/buildtools/FindJsonSchemaBuilder.cmake5
-rw-r--r--cmake/platform/android/android.cmake2
-rw-r--r--cmake/scripts/common/ModuleHelpers.cmake41
-rw-r--r--docs/README.Android.md16
-rw-r--r--project/BuildDependencies/scripts/0_package.target-win10-arm.list2
-rw-r--r--project/BuildDependencies/scripts/0_package.target-win10-win32.list2
-rw-r--r--project/BuildDependencies/scripts/0_package.target-win10-x64.list2
-rw-r--r--project/BuildDependencies/scripts/0_package.target-win32.list2
-rw-r--r--project/BuildDependencies/scripts/0_package.target-x64.list2
-rw-r--r--system/settings/android.xml12
-rwxr-xr-xsystem/settings/settings.xml19
-rw-r--r--system/settings/windows.xml12
-rw-r--r--system/shaders/GL/1.2/gl_shader_vert_clip.glsl39
-rw-r--r--system/shaders/GL/1.2/gl_shader_vert_simple.glsl26
-rw-r--r--system/shaders/GL/1.5/gl_shader_vert_clip.glsl39
-rw-r--r--system/shaders/GL/1.5/gl_shader_vert_simple.glsl26
-rw-r--r--system/shaders/GLES/2.0/gles_shader_clip.vert39
-rw-r--r--system/shaders/GLES/2.0/gles_shader_simple.vert26
-rw-r--r--tools/android/packaging/xbmc/build.gradle.in3
-rw-r--r--tools/android/packaging/xbmc/src/Splash.java.in11
-rw-r--r--tools/buildsteps/defaultenv4
-rw-r--r--tools/depends/configure.ac4
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp16
-rw-r--r--tools/depends/target/dav1d/DAV1D-VERSION4
-rw-r--r--tools/depends/target/ffmpeg/CMakeLists.txt4
-rw-r--r--tools/depends/target/libass/Makefile6
-rw-r--r--tools/depends/target/libnfs/01-MSUWP-compat.patch11
-rw-r--r--tools/depends/target/libnfs/Makefile4
-rw-r--r--tools/depends/target/pcre/Makefile1
-rw-r--r--tools/depends/target/samba-gplv3/samba_android.patch44
-rw-r--r--tools/depends/target/samba/samba_android.patch34
-rw-r--r--xbmc/AutoSwitch.cpp1
-rw-r--r--xbmc/Autorun.cpp5
-rw-r--r--xbmc/BackgroundInfoLoader.cpp1
-rw-r--r--xbmc/CMakeLists.txt2
-rw-r--r--xbmc/CueDocument.cpp1
-rw-r--r--xbmc/FileItem.cpp1314
-rw-r--r--xbmc/FileItem.h203
-rw-r--r--xbmc/FileItemList.cpp1174
-rw-r--r--xbmc/FileItemList.h206
-rw-r--r--xbmc/GUIInfoManager.cpp33
-rw-r--r--xbmc/NfoFile.cpp1
-rw-r--r--xbmc/PartyModeManager.cpp1
-rw-r--r--xbmc/PlayListPlayer.cpp11
-rw-r--r--xbmc/URL.cpp12
-rw-r--r--xbmc/Util.cpp15
-rw-r--r--xbmc/addons/AddonManager.cpp1
-rw-r--r--xbmc/addons/AddonManager.h3
-rw-r--r--xbmc/addons/AddonRepos.cpp97
-rw-r--r--xbmc/addons/AddonRepos.h10
-rw-r--r--xbmc/addons/FilesystemInstaller.cpp1
-rw-r--r--xbmc/addons/Scraper.cpp1
-rw-r--r--xbmc/addons/Skin.cpp1
-rw-r--r--xbmc/addons/VFSEntry.h1
-rw-r--r--xbmc/addons/addoninfo/AddonInfo.cpp1
-rw-r--r--xbmc/addons/gui/GUIDialogAddonInfo.cpp1
-rw-r--r--xbmc/addons/gui/GUIDialogAddonSettings.cpp1
-rw-r--r--xbmc/addons/gui/GUIViewStateAddonBrowser.cpp1
-rw-r--r--xbmc/addons/gui/GUIWindowAddonBrowser.cpp1
-rw-r--r--xbmc/addons/interfaces/Filesystem.cpp1
-rw-r--r--xbmc/addons/interfaces/gui/Window.cpp1
-rw-r--r--xbmc/addons/settings/AddonSettings.cpp1
-rw-r--r--xbmc/application/AppParamParser.cpp1
-rw-r--r--xbmc/application/AppParams.cpp4
-rw-r--r--xbmc/application/AppParams.h2
-rw-r--r--xbmc/application/Application.cpp26
-rw-r--r--xbmc/application/ApplicationPlayer.cpp4
-rw-r--r--xbmc/application/ApplicationPlayerCallback.cpp9
-rw-r--r--xbmc/application/ApplicationSkinHandling.cpp1
-rw-r--r--xbmc/application/ApplicationStackHelper.cpp1
-rw-r--r--xbmc/cdrip/CDDARipper.cpp1
-rw-r--r--xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp2
-rw-r--r--xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp16
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp67
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkDARWINTVOS.mm12
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp4
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkStarfish.cpp55
-rw-r--r--xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp10
-rw-r--r--xbmc/cores/AudioEngine/Utils/AEStreamInfo.h2
-rw-r--r--xbmc/cores/DllLoader/exports/emu_msvcrt.cpp1
-rw-r--r--xbmc/cores/DllLoader/exports/wrapper.c7
-rw-r--r--xbmc/cores/DllLoader/exports/wrapper_mach_alias1
-rw-r--r--xbmc/cores/RetroPlayer/savestates/SavestateDatabase.cpp1
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp255
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecStarfish.cpp164
-rw-r--r--xbmc/cores/VideoPlayer/DVDFileInfo.cpp10
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp5
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp8
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFile.cpp4
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamStack.cpp1
-rw-r--r--xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitlesLibass.cpp1
-rw-r--r--xbmc/cores/VideoPlayer/VideoPlayer.cpp4
-rw-r--r--xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp2
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp1
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGL.cpp5
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGLES.cpp5
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp7
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h2
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h2
-rw-r--r--xbmc/cores/VideoSettings.cpp2
-rw-r--r--xbmc/cores/paplayer/AudioDecoder.cpp2
-rw-r--r--xbmc/cores/playercorefactory/PlayerCoreFactory.cpp5
-rw-r--r--xbmc/cores/playercorefactory/PlayerSelectionRule.cpp20
-rw-r--r--xbmc/cores/playercorefactory/PlayerSelectionRule.h1
-rw-r--r--xbmc/dialogs/GUIDialogColorPicker.cpp1
-rw-r--r--xbmc/dialogs/GUIDialogFileBrowser.cpp1
-rw-r--r--xbmc/dialogs/GUIDialogMediaFilter.cpp1
-rw-r--r--xbmc/dialogs/GUIDialogMediaSource.cpp1
-rw-r--r--xbmc/dialogs/GUIDialogSelect.cpp1
-rw-r--r--xbmc/dialogs/GUIDialogSimpleMenu.cpp6
-rw-r--r--xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp1
-rw-r--r--xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp1
-rw-r--r--xbmc/events/windows/GUIViewStateEventLog.cpp1
-rw-r--r--xbmc/events/windows/GUIWindowEventLog.cpp1
-rw-r--r--xbmc/favourites/FavouritesService.cpp5
-rw-r--r--xbmc/favourites/FavouritesService.h1
-rw-r--r--xbmc/favourites/GUIViewStateFavourites.cpp2
-rw-r--r--xbmc/filesystem/AddonsDirectory.cpp39
-rw-r--r--xbmc/filesystem/AudioBookFileDirectory.cpp1
-rw-r--r--xbmc/filesystem/BlurayCallback.cpp1
-rw-r--r--xbmc/filesystem/BlurayDirectory.cpp1
-rw-r--r--xbmc/filesystem/CDDADirectory.cpp1
-rw-r--r--xbmc/filesystem/DAVDirectory.cpp1
-rw-r--r--xbmc/filesystem/Directorization.h1
-rw-r--r--xbmc/filesystem/Directory.cpp6
-rw-r--r--xbmc/filesystem/DirectoryCache.cpp1
-rw-r--r--xbmc/filesystem/EventsDirectory.cpp1
-rw-r--r--xbmc/filesystem/FTPDirectory.cpp1
-rw-r--r--xbmc/filesystem/HTTPDirectory.cpp1
-rw-r--r--xbmc/filesystem/ISO9660Directory.cpp1
-rw-r--r--xbmc/filesystem/LibraryDirectory.cpp1
-rw-r--r--xbmc/filesystem/MultiPathDirectory.cpp1
-rw-r--r--xbmc/filesystem/MusicDatabaseDirectory.cpp1
-rw-r--r--xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.cpp1
-rw-r--r--xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumRecentlyAdded.cpp1
-rw-r--r--xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumRecentlyPlayed.cpp1
-rw-r--r--xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbumTop100.cpp1
-rw-r--r--xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp1
-rw-r--r--xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeTop100.cpp1
-rw-r--r--xbmc/filesystem/MusicFileDirectory.cpp1
-rw-r--r--xbmc/filesystem/MusicSearchDirectory.cpp1
-rw-r--r--xbmc/filesystem/NFSDirectory.cpp1
-rw-r--r--xbmc/filesystem/PlaylistDirectory.cpp1
-rw-r--r--xbmc/filesystem/PlaylistFileDirectory.cpp1
-rw-r--r--xbmc/filesystem/PluginDirectory.cpp1
-rw-r--r--xbmc/filesystem/RSSDirectory.cpp1
-rw-r--r--xbmc/filesystem/ResourceDirectory.cpp1
-rw-r--r--xbmc/filesystem/SmartPlaylistDirectory.cpp1
-rw-r--r--xbmc/filesystem/SourcesDirectory.cpp9
-rw-r--r--xbmc/filesystem/SpecialProtocolDirectory.cpp1
-rw-r--r--xbmc/filesystem/StackDirectory.cpp1
-rw-r--r--xbmc/filesystem/UDFDirectory.cpp1
-rw-r--r--xbmc/filesystem/UPnPDirectory.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeEpisodes.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeInProgressTvShows.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMusicVideosOverview.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedEpisodes.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMovies.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMusicVideos.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMusicVideos.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleTvShows.cpp1
-rw-r--r--xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTvShowsOverview.cpp1
-rw-r--r--xbmc/filesystem/VirtualDirectory.cpp1
-rw-r--r--xbmc/filesystem/ZeroconfDirectory.cpp1
-rw-r--r--xbmc/filesystem/test/TestDirectory.cpp1
-rw-r--r--xbmc/filesystem/test/TestHTTPDirectory.cpp1
-rw-r--r--xbmc/filesystem/test/TestZipFile.cpp1
-rw-r--r--xbmc/games/addons/GameClientProperties.cpp1
-rw-r--r--xbmc/games/agents/windows/GUIAgentControllerList.cpp1
-rw-r--r--xbmc/games/controllers/dialogs/ControllerInstaller.cpp1
-rw-r--r--xbmc/games/controllers/dialogs/ControllerSelect.cpp1
-rw-r--r--xbmc/games/dialogs/GUIDialogSelectGameClient.cpp1
-rw-r--r--xbmc/games/dialogs/osd/DialogGameSaves.cpp1
-rw-r--r--xbmc/games/dialogs/osd/DialogGameStretchMode.cpp1
-rw-r--r--xbmc/games/dialogs/osd/DialogGameVideoFilter.h1
-rw-r--r--xbmc/games/dialogs/osd/DialogGameVideoRotation.cpp1
-rw-r--r--xbmc/games/dialogs/osd/DialogGameVideoSelect.cpp1
-rw-r--r--xbmc/games/dialogs/osd/DialogInGameSaves.h1
-rw-r--r--xbmc/games/ports/guicontrols/GUIActivePortList.cpp1
-rw-r--r--xbmc/games/ports/windows/GUIPortList.cpp1
-rw-r--r--xbmc/games/windows/GUIViewStateWindowGames.cpp1
-rw-r--r--xbmc/games/windows/GUIWindowGames.cpp1
-rw-r--r--xbmc/guilib/GUIBaseContainer.cpp12
-rw-r--r--xbmc/guilib/GUIControl.cpp22
-rw-r--r--xbmc/guilib/GUIControl.h5
-rw-r--r--xbmc/guilib/GUIFont.cpp16
-rw-r--r--xbmc/guilib/GUIFontManager.cpp1
-rw-r--r--xbmc/guilib/GUIFontTTF.cpp93
-rw-r--r--xbmc/guilib/GUIFontTTF.h12
-rw-r--r--xbmc/guilib/GUIFontTTFGL.cpp130
-rw-r--r--xbmc/guilib/GUIFontTTFGL.h4
-rw-r--r--xbmc/guilib/GUIFontTTFGLES.cpp114
-rw-r--r--xbmc/guilib/GUIFontTTFGLES.h1
-rw-r--r--xbmc/guilib/GUIIncludes.cpp3
-rw-r--r--xbmc/guilib/GUILabelControl.dox4
-rw-r--r--xbmc/guilib/GUIMultiImage.cpp1
-rw-r--r--xbmc/guilib/GUITextLayout.cpp135
-rw-r--r--xbmc/guilib/TextureGL.cpp11
-rw-r--r--xbmc/guilib/guiinfo/GUIInfoLabels.h3
-rw-r--r--xbmc/guilib/guiinfo/LibraryGUIInfo.cpp1
-rw-r--r--xbmc/guilib/guiinfo/PicturesGUIInfo.cpp4
-rw-r--r--xbmc/guilib/guiinfo/PlayerGUIInfo.cpp2
-rw-r--r--xbmc/guilib/guiinfo/SystemGUIInfo.cpp15
-rw-r--r--xbmc/guilib/guiinfo/VideoGUIInfo.cpp10
-rw-r--r--xbmc/guilib/listproviders/DirectoryProvider.cpp4
-rw-r--r--xbmc/input/keyboard/KeyboardLayoutManager.cpp1
-rw-r--r--xbmc/input/keymaps/ButtonTranslator.cpp1
-rw-r--r--xbmc/interfaces/AnnouncementManager.cpp4
-rw-r--r--xbmc/interfaces/builtins/PlayerBuiltins.cpp12
-rw-r--r--xbmc/interfaces/json-rpc/AddonsOperations.cpp10
-rw-r--r--xbmc/interfaces/json-rpc/AddonsOperations.h3
-rw-r--r--xbmc/interfaces/json-rpc/AudioLibrary.cpp1
-rw-r--r--xbmc/interfaces/json-rpc/FileItemHandler.cpp1
-rw-r--r--xbmc/interfaces/json-rpc/FileOperations.cpp1
-rw-r--r--xbmc/interfaces/json-rpc/PVROperations.cpp1
-rw-r--r--xbmc/interfaces/json-rpc/PlayerOperations.cpp1
-rw-r--r--xbmc/interfaces/json-rpc/PlaylistOperations.cpp1
-rw-r--r--xbmc/interfaces/json-rpc/ProfilesOperations.cpp1
-rw-r--r--xbmc/interfaces/json-rpc/TextureOperations.cpp1
-rw-r--r--xbmc/interfaces/json-rpc/VideoLibrary.cpp1
-rw-r--r--xbmc/interfaces/legacy/Control.cpp1
-rw-r--r--xbmc/interfaces/legacy/Dialog.cpp1
-rw-r--r--xbmc/interfaces/legacy/ModuleXbmcplugin.cpp1
-rw-r--r--xbmc/interfaces/legacy/ModuleXbmcvfs.cpp1
-rw-r--r--xbmc/interfaces/legacy/PlayList.cpp1
-rw-r--r--xbmc/interfaces/legacy/Player.cpp1
-rw-r--r--xbmc/interfaces/legacy/WindowXML.cpp1
-rw-r--r--xbmc/music/ContextMenus.cpp8
-rw-r--r--xbmc/music/GUIViewStateMusic.cpp6
-rw-r--r--xbmc/music/MusicDatabase.cpp1
-rw-r--r--xbmc/music/MusicInfoLoader.cpp1
-rw-r--r--xbmc/music/MusicUtils.cpp7
-rw-r--r--xbmc/music/dialogs/GUIDialogMusicInfo.cpp1
-rw-r--r--xbmc/music/dialogs/GUIDialogSongInfo.h1
-rw-r--r--xbmc/music/infoscanner/MusicInfoScanner.cpp1
-rw-r--r--xbmc/music/windows/GUIWindowMusicBase.cpp12
-rw-r--r--xbmc/music/windows/GUIWindowMusicNav.cpp15
-rw-r--r--xbmc/music/windows/GUIWindowMusicPlaylist.cpp1
-rw-r--r--xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp1
-rw-r--r--xbmc/music/windows/MusicFileItemListModifier.cpp1
-rw-r--r--xbmc/network/AirPlayServer.cpp1
-rw-r--r--xbmc/network/upnp/UPnPInternal.cpp12
-rw-r--r--xbmc/network/upnp/UPnPPlayer.cpp8
-rw-r--r--xbmc/network/upnp/UPnPRenderer.cpp6
-rw-r--r--xbmc/network/upnp/UPnPServer.cpp11
-rw-r--r--xbmc/peripherals/addons/PeripheralAddon.cpp1
-rw-r--r--xbmc/peripherals/bus/PeripheralBus.cpp1
-rw-r--r--xbmc/peripherals/dialogs/GUIDialogPeripherals.h1
-rw-r--r--xbmc/pictures/GUIDialogPictureInfo.cpp1
-rw-r--r--xbmc/pictures/GUIViewStatePictures.cpp1
-rw-r--r--xbmc/pictures/GUIWindowPictures.cpp7
-rw-r--r--xbmc/pictures/GUIWindowSlideShow.cpp39
-rw-r--r--xbmc/pictures/PictureFolderImageFileLoader.cpp1
-rw-r--r--xbmc/pictures/PictureInfoLoader.cpp10
-rw-r--r--xbmc/pictures/PictureThumbLoader.cpp6
-rw-r--r--xbmc/platform/android/activity/XBMCApp.cpp109
-rw-r--r--xbmc/platform/android/activity/XBMCApp.h5
-rw-r--r--xbmc/platform/android/filesystem/APKDirectory.cpp1
-rw-r--r--xbmc/platform/android/filesystem/AndroidAppDirectory.cpp1
-rw-r--r--xbmc/platform/android/network/NetworkAndroid.cpp14
-rw-r--r--xbmc/platform/android/storage/AndroidStorageProvider.cpp99
-rw-r--r--xbmc/platform/darwin/osx/MediaKeys.mm30
-rw-r--r--xbmc/platform/darwin/tvos/TVOSTopShelf.mm1
-rw-r--r--xbmc/platform/darwin/tvos/filesystem/TVOSDirectory.cpp1
-rw-r--r--xbmc/platform/posix/CMakeLists.txt2
-rw-r--r--xbmc/platform/posix/PosixTimezone.cpp285
-rw-r--r--xbmc/platform/posix/PosixTimezone.h60
-rw-r--r--xbmc/platform/posix/XTimeUtils.cpp5
-rw-r--r--xbmc/platform/posix/filesystem/PosixDirectory.cpp1
-rw-r--r--xbmc/platform/posix/filesystem/SMBDirectory.cpp1
-rw-r--r--xbmc/platform/posix/filesystem/SMBWSDiscovery.cpp1
-rw-r--r--xbmc/platform/win10/filesystem/WinLibraryDirectory.cpp1
-rw-r--r--xbmc/platform/win32/filesystem/Win32Directory.cpp1
-rw-r--r--xbmc/platform/win32/filesystem/Win32SMBDirectory.cpp1
-rw-r--r--xbmc/playlists/PlayList.cpp1
-rw-r--r--xbmc/playlists/PlayListM3U.cpp5
-rw-r--r--xbmc/playlists/PlayListPLS.cpp5
-rw-r--r--xbmc/playlists/SmartPlaylistFileItemListModifier.cpp1
-rw-r--r--xbmc/profiles/dialogs/GUIDialogProfileSettings.cpp1
-rw-r--r--xbmc/profiles/windows/GUIWindowSettingsProfile.cpp1
-rw-r--r--xbmc/programs/GUIViewStatePrograms.cpp1
-rw-r--r--xbmc/programs/GUIWindowPrograms.cpp1
-rw-r--r--xbmc/pvr/PVRChannelGroupImageFileLoader.cpp1
-rw-r--r--xbmc/pvr/PVRThumbLoader.cpp1
-rw-r--r--xbmc/pvr/dialogs/GUIDialogPVRChannelGuide.cpp1
-rw-r--r--xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp1
-rw-r--r--xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp1
-rw-r--r--xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp1
-rw-r--r--xbmc/pvr/dialogs/GUIDialogPVRItemsViewBase.cpp1
-rw-r--r--xbmc/pvr/filesystem/PVRGUIDirectory.cpp1
-rw-r--r--xbmc/pvr/guilib/GUIEPGGridContainer.cpp1
-rw-r--r--xbmc/pvr/guilib/GUIEPGGridContainerModel.cpp1
-rw-r--r--xbmc/pvr/guilib/PVRGUIActionsDatabase.cpp1
-rw-r--r--xbmc/pvr/guilib/PVRGUIActionsPlayback.cpp1
-rw-r--r--xbmc/pvr/guilib/PVRGUIActionsRecordings.cpp1
-rw-r--r--xbmc/pvr/guilib/PVRGUIActionsUtils.cpp1
-rw-r--r--xbmc/pvr/guilib/PVRGUIChannelIconUpdater.cpp1
-rw-r--r--xbmc/pvr/windows/GUIViewStatePVR.cpp1
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRBase.cpp1
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRChannels.cpp1
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRGuide.cpp1
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRRecordings.cpp1
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRSearch.cpp1
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRTimerRules.cpp1
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRTimers.cpp1
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp1
-rw-r--r--xbmc/rendering/gl/GLShader.cpp6
-rw-r--r--xbmc/rendering/gl/GLShader.h8
-rw-r--r--xbmc/rendering/gl/RenderSystemGL.cpp47
-rw-r--r--xbmc/rendering/gl/RenderSystemGL.h7
-rw-r--r--xbmc/rendering/gles/GLESShader.cpp3
-rw-r--r--xbmc/rendering/gles/GLESShader.h6
-rw-r--r--xbmc/rendering/gles/RenderSystemGLES.cpp40
-rw-r--r--xbmc/rendering/gles/RenderSystemGLES.h5
-rw-r--r--xbmc/settings/AdvancedSettings.cpp37
-rw-r--r--xbmc/settings/AdvancedSettings.h5
-rw-r--r--xbmc/settings/MediaSettings.cpp2
-rw-r--r--xbmc/settings/Settings.cpp45
-rw-r--r--xbmc/settings/Settings.h3
-rw-r--r--xbmc/settings/dialogs/GUIDialogSettingsBase.cpp13
-rw-r--r--xbmc/settings/windows/GUIControlSettings.cpp1
-rw-r--r--xbmc/test/TestBasicEnvironment.cpp1
-rw-r--r--xbmc/utils/ExecString.cpp5
-rw-r--r--xbmc/utils/FileOperationJob.h1
-rw-r--r--xbmc/utils/FontUtils.cpp1
-rw-r--r--xbmc/utils/Geometry.h5
-rw-r--r--xbmc/utils/GroupUtils.cpp6
-rw-r--r--xbmc/utils/RecentlyAddedJob.cpp1
-rw-r--r--xbmc/utils/SaveFileStateJob.cpp7
-rw-r--r--xbmc/utils/URIUtils.cpp10
-rw-r--r--xbmc/utils/test/TestVariant.cpp2
-rw-r--r--xbmc/video/CMakeLists.txt2
-rw-r--r--xbmc/video/ContextMenus.cpp17
-rw-r--r--xbmc/video/GUIViewStateVideo.cpp7
-rw-r--r--xbmc/video/VideoDatabase.cpp34
-rw-r--r--xbmc/video/VideoFileItemClassify.cpp147
-rw-r--r--xbmc/video/VideoFileItemClassify.h47
-rw-r--r--xbmc/video/VideoGeneratedImageFileLoader.cpp7
-rw-r--r--xbmc/video/VideoInfoScanner.cpp15
-rw-r--r--xbmc/video/VideoItemArtworkHandler.cpp5
-rw-r--r--xbmc/video/VideoThumbLoader.cpp18
-rw-r--r--xbmc/video/VideoUtils.cpp32
-rw-r--r--xbmc/video/VideoUtils.h9
-rw-r--r--xbmc/video/dialogs/GUIDialogCMSSettings.cpp1
-rw-r--r--xbmc/video/dialogs/GUIDialogSubtitles.cpp1
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp6
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoInfo.cpp23
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoManager.cpp16
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoManager.h1
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoManagerExtras.cpp1
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoManagerVersions.cpp1
-rw-r--r--xbmc/video/guilib/VideoGUIUtils.cpp16
-rw-r--r--xbmc/video/guilib/VideoSelectActionProcessor.cpp1
-rw-r--r--xbmc/video/guilib/VideoVersionHelper.cpp28
-rw-r--r--xbmc/video/guilib/VideoVersionHelper.h7
-rw-r--r--xbmc/video/jobs/VideoLibraryMarkWatchedJob.cpp1
-rw-r--r--xbmc/video/jobs/VideoLibraryRefreshingJob.cpp1
-rw-r--r--xbmc/video/jobs/VideoLibraryResetResumePointJob.cpp5
-rw-r--r--xbmc/video/tags/VideoTagLoaderNFO.cpp1
-rw-r--r--xbmc/video/tags/VideoTagLoaderPlugin.cpp1
-rw-r--r--xbmc/video/test/CMakeLists.txt4
-rw-r--r--xbmc/video/test/TestStacks.cpp1
-rw-r--r--xbmc/video/test/TestVideoFileItemClassify.cpp219
-rw-r--r--xbmc/video/test/TestVideoUtils.cpp58
-rw-r--r--xbmc/video/windows/GUIWindowVideoBase.cpp61
-rw-r--r--xbmc/video/windows/GUIWindowVideoNav.cpp23
-rw-r--r--xbmc/video/windows/GUIWindowVideoPlaylist.cpp5
-rw-r--r--xbmc/video/windows/VideoFileItemListModifier.cpp7
-rw-r--r--xbmc/view/GUIViewControl.cpp1
-rw-r--r--xbmc/view/GUIViewState.cpp1
-rw-r--r--xbmc/windowing/android/AndroidUtils.cpp162
-rw-r--r--xbmc/windowing/gbm/WinSystemGbm.cpp4
-rw-r--r--xbmc/windowing/osx/OpenGL/OSXGLView.h11
-rw-r--r--xbmc/windowing/osx/OpenGL/OSXGLView.mm21
-rw-r--r--xbmc/windowing/osx/OpenGL/WindowControllerMacOS.mm34
-rw-r--r--xbmc/windowing/osx/WinSystemOSX.h1
-rw-r--r--xbmc/windowing/osx/WinSystemOSX.mm12
-rw-r--r--xbmc/windowing/wayland/CMakeLists.txt2
-rw-r--r--xbmc/windowing/wayland/Seat.cpp9
-rw-r--r--xbmc/windowing/wayland/Seat.h10
-rw-r--r--xbmc/windowing/wayland/SeatWebOS.cpp29
-rw-r--r--xbmc/windowing/wayland/SeatWebOS.h33
-rw-r--r--xbmc/windowing/wayland/WinSystemWayland.cpp29
-rw-r--r--xbmc/windowing/wayland/WinSystemWayland.h4
-rw-r--r--xbmc/windowing/wayland/WinSystemWaylandWebOS.cpp6
-rw-r--r--xbmc/windowing/wayland/WinSystemWaylandWebOS.h1
-rw-r--r--xbmc/windowing/win10/WinSystemWin10.cpp9
-rw-r--r--xbmc/windowing/win10/WinSystemWin10.h4
-rw-r--r--xbmc/windowing/win10/WinSystemWin10DX.cpp17
-rw-r--r--xbmc/windows/GUIMediaWindow.cpp6
-rw-r--r--xbmc/windows/GUIWindowFileManager.cpp4
-rw-r--r--xbmc/windows/GUIWindowLoginScreen.cpp1
404 files changed, 4163 insertions, 3364 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index 9fb3dcb2b0..cbf612389c 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -8078,15 +8078,7 @@ msgctxt "#14078"
msgid "Colours"
msgstr ""
-#: system/settings/settings.xml
-msgctxt "#14079"
-msgid "Timezone country"
-msgstr ""
-
-#: system/settings/settings.xml
-msgctxt "#14080"
-msgid "Timezone"
-msgstr ""
+#empty strings from id 14072 to 14073
#: system/settings/settings.xml
msgctxt "#14081"
@@ -19221,17 +19213,7 @@ msgctxt "#36116"
msgid "Choose which character set is used for displaying text in the user interface. This doesn't change the character set used for subtitles, for that go to Player > Language."
msgstr ""
-#. Description of setting with label #14079 "Timezone country"
-#: system/settings/settings.xml
-msgctxt "#36117"
-msgid "Select country location."
-msgstr ""
-
-#. Description of setting with label #14080 "Timezone"
-#: system/settings/settings.xml
-msgctxt "#36118"
-msgid "Select your current timezone."
-msgstr ""
+#empty strings from id 36117 to 36118
#. Description of setting with label #285 "Preferred audio language"
#: system/settings/settings.xml
diff --git a/cmake/modules/FindFFMPEG.cmake b/cmake/modules/FindFFMPEG.cmake
index 6c6bf973de..76857b0cca 100644
--- a/cmake/modules/FindFFMPEG.cmake
+++ b/cmake/modules/FindFFMPEG.cmake
@@ -55,6 +55,11 @@ macro(buildFFMPEG)
-DOS=${OS}
-DCMAKE_AR=${CMAKE_AR})
endif()
+
+ if(USE_LTO)
+ list(APPEND FFMPEG_OPTIONS -DUSE_LTO=ON)
+ endif()
+
set(LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS})
list(APPEND LINKER_FLAGS ${SYSTEM_LDFLAGS})
diff --git a/cmake/modules/FindFlatBuffers.cmake b/cmake/modules/FindFlatBuffers.cmake
index 6ddfa389c1..aba609933a 100644
--- a/cmake/modules/FindFlatBuffers.cmake
+++ b/cmake/modules/FindFlatBuffers.cmake
@@ -9,15 +9,10 @@
find_package(FlatC REQUIRED)
if(NOT TARGET flatbuffers::flatbuffers)
- if(ENABLE_INTERNAL_FLATBUFFERS)
- include(cmake/scripts/common/ModuleHelpers.cmake)
- set(MODULE_LC flatbuffers)
- # Duplicate URL may exist from FindFlatC.cmake
- # unset otherwise it thinks we are providing a local file location and incorrect concatenation happens
- unset(FLATBUFFERS_URL)
- SETUP_BUILD_VARS()
+ include(cmake/scripts/common/ModuleHelpers.cmake)
+ macro(buildflatbuffers)
# Override build type detection and always build as release
set(FLATBUFFERS_BUILD_TYPE Release)
@@ -33,6 +28,22 @@ if(NOT TARGET flatbuffers::flatbuffers)
set(BUILD_BYPRODUCTS ${DEPENDS_PATH}/include/flatbuffers/flatbuffers.h)
BUILD_DEP_TARGET()
+ endmacro()
+
+ set(MODULE_LC flatbuffers)
+
+ SETUP_BUILD_VARS()
+
+ find_package(flatbuffers CONFIG
+ HINTS ${DEPENDS_PATH}/lib/cmake
+ ${${CORE_PLATFORM_NAME_LC}_SEARCH_CONFIG})
+
+ # Check for existing Flatbuffers. If version >= FLATBUFFERS-VERSION file version, dont build
+ # A corner case, but if a linux/freebsd user WANTS to build internal flatbuffers, build anyway
+ if((flatbuffers_VERSION VERSION_LESS ${${MODULE}_VER} AND ENABLE_INTERNAL_FLATBUFFERS) OR
+ ((CORE_SYSTEM_NAME STREQUAL linux OR CORE_SYSTEM_NAME STREQUAL freebsd) AND ENABLE_INTERNAL_FLATBUFFERS))
+
+ buildflatbuffers()
else()
find_path(FLATBUFFERS_INCLUDE_DIR NAMES flatbuffers/flatbuffers.h
HINTS ${DEPENDS_PATH}/include
@@ -54,5 +65,22 @@ if(NOT TARGET flatbuffers::flatbuffers)
if(TARGET flatbuffers)
add_dependencies(flatbuffers::flatbuffers flatbuffers)
endif()
+
+ # Add internal build target when a Multi Config Generator is used
+ # We cant add a dependency based off a generator expression for targeted build types,
+ # https://gitlab.kitware.com/cmake/cmake/-/issues/19467
+ # therefore if the find heuristics only find the library, we add the internal build
+ # target to the project to allow user to manually trigger for any build type they need
+ # in case only a specific build type is actually available (eg Release found, Debug Required)
+ # This is mainly targeted for windows who required different runtime libs for different
+ # types, and they arent compatible
+ if(_multiconfig_generator)
+ if(NOT TARGET flatbuffers)
+ buildflatbuffers()
+ set_target_properties(flatbuffers PROPERTIES EXCLUDE_FROM_ALL TRUE)
+ endif()
+ add_dependencies(build_internal_depends flatbuffers)
+ endif()
+
set_property(GLOBAL APPEND PROPERTY INTERNAL_DEPS_PROP flatbuffers::flatbuffers)
endif()
diff --git a/cmake/modules/FindNFS.cmake b/cmake/modules/FindNFS.cmake
index 9da2a3ca56..2250093749 100644
--- a/cmake/modules/FindNFS.cmake
+++ b/cmake/modules/FindNFS.cmake
@@ -16,6 +16,14 @@ if(NOT TARGET libnfs::nfs)
-DENABLE_UTILS=OFF
-DENABLE_EXAMPLES=OFF)
+ if(WIN32 OR WINDOWS_STORE)
+ set(${MODULE}_C_FLAGS "/sdl-")
+ set(${MODULE}_CXX_FLAGS "/sdl-")
+
+ set(patches "${CORE_SOURCE_DIR}/tools/depends/target/${MODULE_LC}/01-MSUWP-compat.patch")
+ generate_patchcommand("${patches}")
+ endif()
+
BUILD_DEP_TARGET()
set(_nfs_definitions HAS_NFS_SET_TIMEOUT
diff --git a/cmake/modules/FindPCRE.cmake b/cmake/modules/FindPCRE.cmake
index 578c4b8923..e662d82116 100644
--- a/cmake/modules/FindPCRE.cmake
+++ b/cmake/modules/FindPCRE.cmake
@@ -33,11 +33,16 @@ macro(buildPCRE)
-DPCRE_SUPPORT_UNICODE_PROPERTIES=ON
-DPCRE_SUPPORT_LIBZ=OFF
-DPCRE_SUPPORT_LIBBZ2=OFF
+ -DPCRE_BUILD_PCRECPP=OFF
-DPCRE_BUILD_PCREGREP=OFF
-DPCRE_BUILD_TESTS=OFF)
if(WIN32 OR WINDOWS_STORE)
list(APPEND CMAKE_ARGS -DINSTALL_MSVC_PDB=ON)
+
+ # PCRE fails due to C4703 and C4146 when /SDL is enabled
+ set(PCRE_C_FLAGS "/sdl-")
+ set(PCRE_CXX_FLAGS "/sdl-")
elseif(CORE_SYSTEM_NAME STREQUAL android)
# CMake CheckFunctionExists incorrectly detects strtoq for android
list(APPEND CMAKE_ARGS -DHAVE_STRTOQ=0)
diff --git a/cmake/modules/FindTagLib.cmake b/cmake/modules/FindTagLib.cmake
index 6a85cc4383..78a0eeeccb 100644
--- a/cmake/modules/FindTagLib.cmake
+++ b/cmake/modules/FindTagLib.cmake
@@ -57,8 +57,8 @@ if(NOT TARGET TagLib::TagLib)
SETUP_BUILD_VARS()
# Taglib installs a shell script for all platforms. This can provide version universally
- find_program(TAGLIB-CONFIG NAMES taglib-config taglib-config.command
- HINTS ${DEPENDSPATH}/bin)
+ find_program(TAGLIB-CONFIG NAMES taglib-config taglib-config.cmd
+ HINTS ${DEPENDS_PATH}/bin)
if(TAGLIB-CONFIG)
execute_process(COMMAND "${TAGLIB-CONFIG}" --version
diff --git a/cmake/modules/buildtools/FindFlatC.cmake b/cmake/modules/buildtools/FindFlatC.cmake
index 121bcdbdfe..e234d0eff3 100644
--- a/cmake/modules/buildtools/FindFlatC.cmake
+++ b/cmake/modules/buildtools/FindFlatC.cmake
@@ -22,25 +22,24 @@ if(NOT TARGET flatbuffers::flatc)
string(REGEX REPLACE ".* version (.*)" "\\1" FLATBUFFERS_FLATC_VERSION "${FLATBUFFERS_FLATC_VERSION}")
endif()
- set(MODULE_LC flatbuffers)
- set(LIB_TYPE native)
- # Duplicate URL may exist from FindFlatbuffers.cmake
- # unset otherwise it thinks we are providing a local file location and incorrect concatenation happens
- unset(FLATBUFFERS_URL)
+ set(MODULE_LC flatc)
+ set(${MODULE_LC}_MODULE_LOCATION flatbuffers)
+ set(${MODULE_LC}_LIB_TYPE native)
+
SETUP_BUILD_VARS()
if(NOT FLATBUFFERS_FLATC_EXECUTABLE OR
- (ENABLE_INTERNAL_FLATBUFFERS AND NOT "${FLATBUFFERS_FLATC_VERSION}" VERSION_EQUAL "${FLATBUFFERS_VER}"))
+ (ENABLE_INTERNAL_FLATBUFFERS AND NOT "${FLATBUFFERS_FLATC_VERSION}" VERSION_EQUAL "${FLATC_VER}"))
# Override build type detection and always build as release
- set(FLATBUFFERS_BUILD_TYPE Release)
+ set(FLATC_BUILD_TYPE Release)
if(NATIVEPREFIX)
set(INSTALL_DIR "${NATIVEPREFIX}/bin")
- set(FLATBUFFERS_INSTALL_PREFIX ${NATIVEPREFIX})
+ set(FLATC_INSTALL_PREFIX ${NATIVEPREFIX})
else()
set(INSTALL_DIR "${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/bin")
- set(FLATBUFFERS_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR})
+ set(FLATC_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR})
endif()
set(CMAKE_ARGS -DFLATBUFFERS_CODE_COVERAGE=OFF
@@ -54,20 +53,18 @@ if(NOT TARGET flatbuffers::flatc)
# Set host build info for buildtool
if(EXISTS "${NATIVEPREFIX}/share/Toolchain-Native.cmake")
- set(FLATBUFFERS_TOOLCHAIN_FILE "${NATIVEPREFIX}/share/Toolchain-Native.cmake")
+ set(FLATC_TOOLCHAIN_FILE "${NATIVEPREFIX}/share/Toolchain-Native.cmake")
endif()
if(WIN32 OR WINDOWS_STORE)
# Make sure we generate for host arch, not target
- set(FLATBUFFERS_GENERATOR_PLATFORM CMAKE_GENERATOR_PLATFORM ${HOSTTOOLSET})
- set(WIN_DISABLE_PROJECT_FLAGS 1)
+ set(FLATC_GENERATOR_PLATFORM CMAKE_GENERATOR_PLATFORM ${HOSTTOOLSET})
endif()
set(FLATBUFFERS_FLATC_EXECUTABLE ${INSTALL_DIR}/flatc)
- set(BUILD_NAME flatc)
set(BUILD_BYPRODUCTS ${FLATBUFFERS_FLATC_EXECUTABLE})
- set(FLATBUFFERS_FLATC_VERSION ${FLATBUFFERS_VER})
+ set(FLATBUFFERS_FLATC_VERSION ${FLATC_VER})
BUILD_DEP_TARGET()
endif()
diff --git a/cmake/modules/buildtools/FindJsonSchemaBuilder.cmake b/cmake/modules/buildtools/FindJsonSchemaBuilder.cmake
index 0b7b56481d..1b9f2b031d 100644
--- a/cmake/modules/buildtools/FindJsonSchemaBuilder.cmake
+++ b/cmake/modules/buildtools/FindJsonSchemaBuilder.cmake
@@ -28,7 +28,7 @@ if(NOT TARGET JsonSchemaBuilder::JsonSchemaBuilder)
else()
set(MODULE_LC JsonSchemaBuilder)
- set(LIB_TYPE native)
+ set(${MODULE_LC}_LIB_TYPE native)
set(JSONSCHEMABUILDER_DISABLE_VERSION ON)
SETUP_BUILD_VARS()
@@ -52,8 +52,7 @@ if(NOT TARGET JsonSchemaBuilder::JsonSchemaBuilder)
if(WIN32 OR WINDOWS_STORE)
# Make sure we generate for host arch, not target
- set(JSONSCHEMABUILDER_GENERATOR_PLATFORM CMAKE_GENERATOR_PLATFORM WIN32)
- set(WIN_DISABLE_PROJECT_FLAGS 1)
+ set(JSONSCHEMABUILDER_GENERATOR_PLATFORM CMAKE_GENERATOR_PLATFORM ${HOSTTOOLSET})
set(APP_EXTENSION ".exe")
endif()
diff --git a/cmake/platform/android/android.cmake b/cmake/platform/android/android.cmake
index 49105e353d..6a7f71e1ef 100644
--- a/cmake/platform/android/android.cmake
+++ b/cmake/platform/android/android.cmake
@@ -6,6 +6,6 @@ list(APPEND PLATFORM_OPTIONAL_DEPS LibDovi)
# Store SDK compile version
set(TARGET_SDK 34)
# Minimum supported SDK version
-set(TARGET_MINSDK 21)
+set(TARGET_MINSDK 24)
set(${CORE_PLATFORM_NAME_LC}_SEARCH_CONFIG NO_DEFAULT_PATH CACHE STRING "")
diff --git a/cmake/scripts/common/ModuleHelpers.cmake b/cmake/scripts/common/ModuleHelpers.cmake
index 3cf706e372..cd5288d923 100644
--- a/cmake/scripts/common/ModuleHelpers.cmake
+++ b/cmake/scripts/common/ModuleHelpers.cmake
@@ -10,12 +10,12 @@
function(get_versionfile_data)
# Dependency path
- set(MODULE_PATH "${PROJECTSOURCE}/tools/depends/${LIB_TYPE}/${MODULE_LC}")
+ set(MODULE_PATH "${PROJECTSOURCE}/tools/depends/${${MODULE_LC}_LIB_TYPE}/${${MODULE_LC}_MODULE_LOCATION}")
- if(NOT EXISTS "${MODULE_PATH}/${MODULE}-VERSION")
- MESSAGE(FATAL_ERROR "${MODULE}-VERSION does not exist at ${MODULE_PATH}.")
+ if(NOT EXISTS "${MODULE_PATH}/${${MODULE_LC}_MODULE_VERSION}-VERSION")
+ MESSAGE(FATAL_ERROR "${${MODULE_LC}_MODULE_VERSION}-VERSION does not exist at ${MODULE_PATH}.")
else()
- set(${MODULE}_FILE "${MODULE_PATH}/${MODULE}-VERSION")
+ set(${MODULE}_FILE "${MODULE_PATH}/${${MODULE_LC}_MODULE_VERSION}-VERSION")
endif()
file(STRINGS ${${MODULE}_FILE} ${MODULE}_LNAME REGEX "^[ \t]*LIBNAME=")
@@ -123,13 +123,22 @@ endfunction()
macro(SETUP_BUILD_VARS)
string(TOUPPER ${MODULE_LC} MODULE)
+ if(DEFINED ${MODULE_LC}_MODULE_LOCATION)
+ string(TOUPPER ${${MODULE_LC}_MODULE_LOCATION} _MODULE_UPPER)
+ set(${MODULE_LC}_MODULE_VERSION ${_MODULE_UPPER})
+ unset(_MODULE_UPPER)
+ else()
+ set(${MODULE_LC}_MODULE_LOCATION ${MODULE_LC})
+ set(${MODULE_LC}_MODULE_VERSION ${MODULE})
+ endif()
+
# Fall through to target build module dir if not explicitly set
- if(NOT DEFINED LIB_TYPE)
- set(LIB_TYPE "target")
+ if(NOT DEFINED ${MODULE_LC}_LIB_TYPE)
+ set(${MODULE_LC}_LIB_TYPE "target")
endif()
# Location for build type, native or target
- if(LIB_TYPE STREQUAL "target")
+ if(${MODULE_LC}_LIB_TYPE STREQUAL "target")
set(DEP_LOCATION "${DEPENDS_PATH}")
else()
set(DEP_LOCATION "${NATIVEPREFIX}")
@@ -155,19 +164,17 @@ macro(SETUP_BUILD_VARS)
endif()
if(VERBOSE)
message(STATUS "MODULE: ${MODULE}")
- message(STATUS "LIB_TYPE: ${LIB_TYPE}")
+ message(STATUS "${MODULE_LC}_LIB_TYPE: ${${MODULE_LC}_LIB_TYPE}")
message(STATUS "DEP_LOCATION: ${DEP_LOCATION}")
message(STATUS "PROJECTSOURCE: ${PROJECTSOURCE}")
message(STATUS "${MODULE}_URL: ${${MODULE}_URL}")
endif()
- unset(LIB_TYPE)
endmacro()
macro(CLEAR_BUILD_VARS)
# unset all generic variables to insure clean state between macro calls
# Potentially an issue with scope when a macro is used inside a dep that uses a macro
unset(PROJECTSOURCE)
- unset(LIB_TYPE)
unset(BUILD_NAME)
unset(INSTALL_DIR)
unset(CMAKE_ARGS)
@@ -186,6 +193,7 @@ macro(CLEAR_BUILD_VARS)
unset(${MODULE}_GENERATOR_PLATFORM)
unset(${MODULE}_INSTALL_PREFIX)
unset(${MODULE}_TOOLCHAIN_FILE)
+ unset(${MODULE_LC}_LIB_TYPE)
endmacro()
# Macro to create externalproject_add target
@@ -231,7 +239,8 @@ macro(BUILD_DEP_TARGET)
# We can disable adding them with WIN_DISABLE_PROJECT_FLAGS. This is potentially required
# for host build tools (eg flatc) that may be a different arch to the core app
if(WIN32 OR WINDOWS_STORE)
- if(NOT DEFINED WIN_DISABLE_PROJECT_FLAGS)
+ if(NOT (DEFINED WIN_DISABLE_PROJECT_FLAGS OR
+ ${MODULE_LC}_LIB_TYPE STREQUAL "native"))
list(APPEND CMAKE_ARGS "-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} $<$<CONFIG:Debug>:${CMAKE_C_FLAGS_DEBUG}> $<$<CONFIG:Release>:${CMAKE_C_FLAGS_RELEASE}> ${${MODULE}_C_FLAGS}"
"-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} $<$<CONFIG:Debug>:${CMAKE_CXX_FLAGS_DEBUG}> $<$<CONFIG:Release>:${CMAKE_CXX_FLAGS_RELEASE}> ${${MODULE}_CXX_FLAGS}"
"-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS} $<$<CONFIG:Debug>:${CMAKE_EXE_LINKER_FLAGS_DEBUG}> $<$<CONFIG:Release>:${CMAKE_EXE_LINKER_FLAGS_RELEASE}> ${${MODULE}_EXE_LINKER_FLAGS}")
@@ -287,6 +296,16 @@ macro(BUILD_DEP_TARGET)
set(${MODULE}_GENERATOR CMAKE_GENERATOR "Unix Makefiles")
endif()
elseif(MSVC)
+ # Only apply SYSTEM variables for target build libs
+ if(${MODULE_LC}_LIB_TYPE STREQUAL "target")
+ if(DEFINED CMAKE_SYSTEM_VERSION)
+ list(APPEND CMAKE_ARGS -DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION})
+ endif()
+ if(DEFINED CMAKE_SYSTEM_NAME)
+ list(APPEND CMAKE_ARGS -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
+ endif()
+ endif()
+
if(NOT ${MODULE}_GENERATOR)
set(${MODULE}_GENERATOR CMAKE_GENERATOR "${CMAKE_GENERATOR}")
endif()
diff --git a/docs/README.Android.md b/docs/README.Android.md
index 08d04c82a2..72fcf75e7f 100644
--- a/docs/README.Android.md
+++ b/docs/README.Android.md
@@ -73,8 +73,8 @@ sudo apt install autoconf bison build-essential curl default-jdk flex gawk git g
**[back to top](#table-of-contents)**
## 3. Prerequisites
-Building Kodi for Android requires Android NDK revision 20b. For the SDK just use the latest available.
-Kodi CI/CD platforms currently use r21e for build testing and releases, so we recommend using r21e for the most tested build experience
+Building Kodi for Android requires Android NDK revision 26c. For the SDK just use the latest available.
+Kodi CI/CD platforms currently use r26c for build testing and releases, so we recommend using r26c for the most tested build experience
* **[Android SDK](https://developer.android.com/studio/index.html)** (Look for `Get just the command line tools`)
@@ -100,7 +100,7 @@ cd $HOME/android-tools/android-sdk-linux/cmdline-tools/bin
./sdkmanager --sdk_root=$(pwd)/../.. platform-tools
./sdkmanager --sdk_root=$(pwd)/../.. "platforms;android-34"
./sdkmanager --sdk_root=$(pwd)/../.. "build-tools;33.0.1"
-./sdkmanager --sdk_root=$(pwd)/../.. "ndk;21.4.7075529"
+./sdkmanager --sdk_root=$(pwd)/../.. "ndk;26.2.11394342"
```
### 3.3. Create a key to sign debug APKs
@@ -135,22 +135,22 @@ cd $HOME/kodi/tools/depends
Configure build for aarch64:
```
-./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=aarch64-linux-android --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-sdk-linux/ndk/21.4.7075529 --prefix=$HOME/android-tools/xbmc-depends
+./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=aarch64-linux-android --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-sdk-linux/ndk/26.2.11394342 --prefix=$HOME/android-tools/xbmc-depends
```
Or configure build for arm:
```
-./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=arm-linux-androideabi --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-sdk-linux/ndk/21.4.7075529 --prefix=$HOME/android-tools/xbmc-depends
+./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=arm-linux-androideabi --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-sdk-linux/ndk/26.2.11394342 --prefix=$HOME/android-tools/xbmc-depends
```
Or configure build for x86:
```
-./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=i686-linux-android --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-sdk-linux/ndk/21.4.7075529 --prefix=$HOME/android-tools/xbmc-depends
+./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=i686-linux-android --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-sdk-linux/ndk/26.2.11394342 --prefix=$HOME/android-tools/xbmc-depends
```
Or configure build for x86_64:
```
-./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=x86_64-linux-android --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-sdk-linux/ndk/21.4.7075529 --prefix=$HOME/android-tools/xbmc-depends
+./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=x86_64-linux-android --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-sdk-linux/ndk/26.2.11394342 --prefix=$HOME/android-tools/xbmc-depends
```
> [!NOTE]
@@ -238,7 +238,7 @@ make -j$(getconf _NPROCESSORS_ONLN)
```
--with-ndk-api=<ndk number>
```
- specify ndk level (optional for android), default is 21.]
+ specify ndk level (optional for android), default is 24.]
```
--with-ndk-path=<path>
diff --git a/project/BuildDependencies/scripts/0_package.target-win10-arm.list b/project/BuildDependencies/scripts/0_package.target-win10-arm.list
index 50074ebcc1..a3490f9e16 100644
--- a/project/BuildDependencies/scripts/0_package.target-win10-arm.list
+++ b/project/BuildDependencies/scripts/0_package.target-win10-arm.list
@@ -7,7 +7,7 @@
; -> ...
;PLEASE KEEP THIS LIST IN ALPHABETICAL ORDER!
curl-7.67.0-win10-arm-v141-20200105.7z
-dav1d-1.2.0-win10-arm-v142-20230513.7z
+dav1d-1.4.1-win10-arm-v142-20240331.7z
freetype-2.10.1-win10-arm-v141-20200105.7z
fstrcmp-0.7-win10-arm-v141-20200105.7z
GoogleTest-1.10.0-win10-arm-v141-20200410.7z
diff --git a/project/BuildDependencies/scripts/0_package.target-win10-win32.list b/project/BuildDependencies/scripts/0_package.target-win10-win32.list
index bfd07c2644..fda954334d 100644
--- a/project/BuildDependencies/scripts/0_package.target-win10-win32.list
+++ b/project/BuildDependencies/scripts/0_package.target-win10-win32.list
@@ -7,7 +7,7 @@
; -> ...
;PLEASE KEEP THIS LIST IN ALPHABETICAL ORDER!
curl-7.67.0-win10-win32-v141-20200105.7z
-dav1d-1.2.0-win10-win32-v142-20230513.7z
+dav1d-1.4.1-win10-win32-v142-20240331.7z
freetype-2.10.1-win10-win32-v141-20200105.7z
fstrcmp-0.7-win10-win32-v141-20200105.7z
GoogleTest-1.10.0-win10-win32-v141-20200410.7z
diff --git a/project/BuildDependencies/scripts/0_package.target-win10-x64.list b/project/BuildDependencies/scripts/0_package.target-win10-x64.list
index d4d4a26517..2c2635be57 100644
--- a/project/BuildDependencies/scripts/0_package.target-win10-x64.list
+++ b/project/BuildDependencies/scripts/0_package.target-win10-x64.list
@@ -7,7 +7,7 @@
; -> ...
;PLEASE KEEP THIS LIST IN ALPHABETICAL ORDER!
curl-7.67.0-win10-x64-v141-20200105.7z
-dav1d-1.2.0-win10-x64-v142-20230513.7z
+dav1d-1.4.1-win10-x64-v142-20240331.7z
freetype-2.10.1-win10-x64-v141-20200105.7z
fstrcmp-0.7-win10-x64-v141-20200105.7z
GoogleTest-1.10.0-win10-x64-v141-20200410.7z
diff --git a/project/BuildDependencies/scripts/0_package.target-win32.list b/project/BuildDependencies/scripts/0_package.target-win32.list
index 4d531330bb..b0c882344d 100644
--- a/project/BuildDependencies/scripts/0_package.target-win32.list
+++ b/project/BuildDependencies/scripts/0_package.target-win32.list
@@ -7,7 +7,7 @@
; -> ...
;PLEASE KEEP THIS LIST IN ALPHABETICAL ORDER!
curl-7.67.0-win32-v141-20200105.7z
-dav1d-1.2.0-win32-v142-20230513.7z
+dav1d-1.4.1-win32-v142-20240331.7z
detours-64ec13-win32-v141-20200105.7z
dnssd-878.260.1-win32-v141-20200105.7z
freetype-2.10.1-win32-v141-20200105.7z
diff --git a/project/BuildDependencies/scripts/0_package.target-x64.list b/project/BuildDependencies/scripts/0_package.target-x64.list
index eacfd4629d..7ae89f8c4c 100644
--- a/project/BuildDependencies/scripts/0_package.target-x64.list
+++ b/project/BuildDependencies/scripts/0_package.target-x64.list
@@ -7,7 +7,7 @@
; -> ...
;PLEASE KEEP THIS LIST IN ALPHABETICAL ORDER!
curl-7.67.0-x64-v141-20200105.7z
-dav1d-1.2.0-x64-v142-20230513.7z
+dav1d-1.4.1-x64-v142-20240331.7z
detours-64ec13-x64-v141-20200105.7z
dnssd-878.260.1-x64-v141-20200105.7z
freetype-2.10.1-x64-v141-20200105.7z
diff --git a/system/settings/android.xml b/system/settings/android.xml
index 661a978e32..838990389a 100644
--- a/system/settings/android.xml
+++ b/system/settings/android.xml
@@ -29,16 +29,4 @@
</group>
</category>
</section>
- <section id="interface">
- <category id="regional">
- <group id="2">
- <setting id="locale.timezonecountry">
- <visible>false</visible>
- </setting>
- <setting id="locale.timezone">
- <visible>false</visible>
- </setting>
- </group>
- </category>
- </section>
</settings>
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index e48fcf1c08..2317cdf90c 100755
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -4030,25 +4030,6 @@
</dependencies>
<control type="list" format="string" />
</setting>
- <setting id="locale.timezonecountry" type="string" label="14079" help="36117">
- <level>1</level>
- <default>default</default> <!-- will be properly set on startup -->
- <constraints>
- <options>timezonecountries</options>
- </constraints>
- <control type="list" format="string" />
- </setting>
- <setting id="locale.timezone" type="string" label="14080" help="36118">
- <level>1</level>
- <default>default</default> <!-- will be properly set on startup -->
- <constraints>
- <options>timezones</options>
- </constraints>
- <dependencies>
- <dependency type="update" setting="locale.timezonecountry" />
- </dependencies>
- <control type="list" format="string" />
- </setting>
<setting id="locale.shortdateformat" type="string" label="14109" help="36173">
<level>2</level>
<default>regional</default>
diff --git a/system/settings/windows.xml b/system/settings/windows.xml
index 163cb5c2d3..523d0c9cab 100644
--- a/system/settings/windows.xml
+++ b/system/settings/windows.xml
@@ -58,16 +58,4 @@
</group>
</category>
</section>
- <section id="interface">
- <category id="regional">
- <group id="2">
- <setting id="locale.timezonecountry">
- <visible>false</visible>
- </setting>
- <setting id="locale.timezone">
- <visible>false</visible>
- </setting>
- </group>
- </category>
- </section>
</settings>
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/android/packaging/xbmc/build.gradle.in b/tools/android/packaging/xbmc/build.gradle.in
index 14c9c2b6d1..71f94a8ffa 100644
--- a/tools/android/packaging/xbmc/build.gradle.in
+++ b/tools/android/packaging/xbmc/build.gradle.in
@@ -47,6 +47,9 @@ android {
}
packagingOptions{
doNotStrip '**.setup'
+ jniLibs {
+ useLegacyPackaging = true
+ }
}
}
diff --git a/tools/android/packaging/xbmc/src/Splash.java.in b/tools/android/packaging/xbmc/src/Splash.java.in
index ddc3291cd8..19e33a676f 100644
--- a/tools/android/packaging/xbmc/src/Splash.java.in
+++ b/tools/android/packaging/xbmc/src/Splash.java.in
@@ -397,11 +397,7 @@ public class Splash extends Activity
AlertDialog.Builder builder = new AlertDialog.Builder(act);
builder.setTitle(title);
builder.setIcon(android.R.drawable.ic_dialog_alert);
- if (Build.VERSION.SDK_INT >= 24) {
- builder.setMessage(Html.fromHtml(message, Html.FROM_HTML_MODE_LEGACY));
- } else {
- builder.setMessage(Html.fromHtml(message));
- }
+ builder.setMessage(Html.fromHtml(message, Html.FROM_HTML_MODE_LEGACY));
builder.setPositiveButton("Exit", (dialog, arg1) -> {
dialog.dismiss();
act.finish();
@@ -514,16 +510,13 @@ public class Splash extends Activity
retVal = true;
}
}
- else if (Build.VERSION.SDK_INT > 22)
+ else
{
int permissionCheck;
permissionCheck = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionCheck == PERMISSION_GRANTED)
retVal = true;
}
- else
- retVal= true;
-
return retVal;
}
diff --git a/tools/buildsteps/defaultenv b/tools/buildsteps/defaultenv
index b4013ac349..c14478aca9 100644
--- a/tools/buildsteps/defaultenv
+++ b/tools/buildsteps/defaultenv
@@ -56,8 +56,8 @@ case $XBMC_PLATFORM_DIR in
;;
android)
- DEFAULT_NDK_VERSION="21e" # NDK package version (newer API can be inside)
- DEFAULT_NDK_API="21" # Lollipop API level (21) defined in package ./sysroot/usr/include/android/api-level.h
+ DEFAULT_NDK_VERSION="26c" # NDK package version (newer API can be inside)
+ DEFAULT_NDK_API="24" # Nougat API level (24) defined in package ./sysroot/usr/include/android/api-level.h
DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
DEFAULT_CONFIGURATION="RelWithDebInfo"
;;
diff --git a/tools/depends/configure.ac b/tools/depends/configure.ac
index b09b586dc5..9bce943cc0 100644
--- a/tools/depends/configure.ac
+++ b/tools/depends/configure.ac
@@ -87,9 +87,9 @@ AC_ARG_WITH([sdk],
AC_ARG_WITH([ndk-api],
[AS_HELP_STRING([--with-ndk-api],
- [specify ndk level (optional for android), default is 21.])],
+ [specify ndk level (optional for android), default is 24.])],
[use_ndk_api=$withval],
- [use_ndk_api=21])
+ [use_ndk_api=24])
AC_ARG_ENABLE([gplv3],
[AS_HELP_STRING([--enable-gplv3],
diff --git a/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp
index 452c865bdd..450adc1e93 100644
--- a/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp
+++ b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp
@@ -22,6 +22,8 @@
#include "SimpleFS.h"
+#include <cstdint>
+#include <limits>
#include <memory>
#include <jpeglib.h>
@@ -80,8 +82,6 @@ bool JPGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames)
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
- int ImageSize;
-
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
@@ -89,12 +89,18 @@ bool JPGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames)
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
- // Image Size is calculated as (width * height * bytes per pixel = 4
- ImageSize = cinfo.image_width * cinfo.image_height * 4;
+ // Image Size is calculated as width * height * bytes per pixel = 4
+ // Since image_width and image_height can be at most 0xFFFF, this is safe from overflows
+ const std::uint64_t ImageSize =
+ static_cast<std::uint64_t>(cinfo.image_width) * cinfo.image_height * 4;
+
+ // Check if the conversion to std::size_t is lossless
+ if (ImageSize > std::numeric_limits<std::size_t>::max())
+ return false;
DecodedFrame frame;
- frame.rgbaImage.pixels.resize(ImageSize);
+ frame.rgbaImage.pixels.resize(static_cast<std::size_t>(ImageSize));
std::vector<unsigned char> scanlinebuff;
scanlinebuff.resize(3 * cinfo.image_width);
diff --git a/tools/depends/target/dav1d/DAV1D-VERSION b/tools/depends/target/dav1d/DAV1D-VERSION
index 7897d53556..f803959d0f 100644
--- a/tools/depends/target/dav1d/DAV1D-VERSION
+++ b/tools/depends/target/dav1d/DAV1D-VERSION
@@ -1,5 +1,5 @@
LIBNAME=dav1d
-VERSION=1.1.0
+VERSION=1.4.1
ARCHIVE=$(LIBNAME)-$(VERSION).tar.bz2
-SHA512=2eb177b415d1ac7bd08d54b16375afedec61f0771a5181fa93e5e6215856fc26504a7cb47de08abbea5bf18fac5ff91ca31044e7054681c380e0ab152e53aabc
+SHA512=b2dcdeeb3d6c37788b4c697b497b9282738b758927ffbdbe72b05b1b26a61aa967dfba0ce05828b5bd5bcac93eb3394b0eafbb57e325d037867cf720d64ba099
BYPRODUCT=libdav1d.a
diff --git a/tools/depends/target/ffmpeg/CMakeLists.txt b/tools/depends/target/ffmpeg/CMakeLists.txt
index 0bbc23540a..5cadafe294 100644
--- a/tools/depends/target/ffmpeg/CMakeLists.txt
+++ b/tools/depends/target/ffmpeg/CMakeLists.txt
@@ -121,6 +121,10 @@ if(CPU MATCHES x86 OR CPU MATCHES x86_64)
list(APPEND ffmpeg_conf --x86asmexe=${NASM_EXECUTABLE})
endif()
+if(USE_LTO)
+ list(APPEND ffmpeg_conf --enable-lto)
+endif()
+
if(ENABLE_DAV1D)
list(APPEND ffmpeg_conf --enable-libdav1d)
set(pkgconf_path "PKG_CONFIG_PATH=${PKG_CONFIG_PATH}")
diff --git a/tools/depends/target/libass/Makefile b/tools/depends/target/libass/Makefile
index 4be63dce6f..94bfcac3fa 100644
--- a/tools/depends/target/libass/Makefile
+++ b/tools/depends/target/libass/Makefile
@@ -1,12 +1,6 @@
include ../../Makefile.include LIBASS-VERSION ../../download-files.include
DEPS = ../../Makefile.include Makefile LIBASS-VERSION ../../download-files.include
-ifeq ($(OS),android)
- # Android API Level 21/22 requires explicit link.
- # This doesnt appear to be required for API Level 23+ (Android 6+)
- export LDFLAGS+= -lstdc++
-endif
-
# configuration settings
CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \
./configure --prefix=$(PREFIX) \
diff --git a/tools/depends/target/libnfs/01-MSUWP-compat.patch b/tools/depends/target/libnfs/01-MSUWP-compat.patch
new file mode 100644
index 0000000000..70cac0b767
--- /dev/null
+++ b/tools/depends/target/libnfs/01-MSUWP-compat.patch
@@ -0,0 +1,11 @@
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -39,7 +39,7 @@
+ add_definitions(-Dlibnfs_EXPORTS)
+ endif()
+
+-if(CMAKE_SYSTEM_NAME STREQUAL Windows)
++if(CMAKE_SYSTEM_NAME MATCHES "Windows")
+ add_definitions("-D_U_=" -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
+ list(APPEND SYSTEM_LIBRARIES ws2_32)
+ add_subdirectory(win32)
diff --git a/tools/depends/target/libnfs/Makefile b/tools/depends/target/libnfs/Makefile
index f4cfd33a37..e069bbf790 100644
--- a/tools/depends/target/libnfs/Makefile
+++ b/tools/depends/target/libnfs/Makefile
@@ -1,5 +1,6 @@
include ../../Makefile.include LIBNFS-VERSION ../../download-files.include
-DEPS= ../../Makefile.include Makefile LIBNFS-VERSION ../../download-files.include
+DEPS= ../../Makefile.include Makefile LIBNFS-VERSION ../../download-files.include \
+ 01-MSUWP-compat.patch
# configuration settings
CMAKE_OPTIONS=-DBUILD_SHARED_LIBS=OFF \
@@ -16,6 +17,7 @@ $(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
-rm -rf $(PLATFORM); mkdir -p $(PLATFORM)
cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
cd $(PLATFORM); mkdir -p build
+ cd $(PLATFORM); patch -p1 -i ../01-MSUWP-compat.patch
cd $(PLATFORM)/build; $(CMAKE) $(CMAKE_OPTIONS) ..
$(LIBDYLIB): $(PLATFORM)
diff --git a/tools/depends/target/pcre/Makefile b/tools/depends/target/pcre/Makefile
index 3c682a4949..679a6c058b 100644
--- a/tools/depends/target/pcre/Makefile
+++ b/tools/depends/target/pcre/Makefile
@@ -18,6 +18,7 @@ CMAKE_OPTIONS=-DPCRE_NEWLINE=ANYCRLF \
-DPCRE_SUPPORT_UNICODE_PROPERTIES=ON \
-DPCRE_SUPPORT_LIBZ=OFF \
-DPCRE_SUPPORT_LIBBZ2=OFF \
+ -DPCRE_BUILD_PCRECPP=OFF \
-DPCRE_BUILD_PCREGREP=OFF \
-DPCRE_BUILD_TESTS=OFF \
-DCMAKE_BUILD_TYPE=Release
diff --git a/tools/depends/target/samba-gplv3/samba_android.patch b/tools/depends/target/samba-gplv3/samba_android.patch
index 3d194cfa8f..a6c4007e1a 100644
--- a/tools/depends/target/samba-gplv3/samba_android.patch
+++ b/tools/depends/target/samba-gplv3/samba_android.patch
@@ -1,36 +1,3 @@
---- a/lib/util/charset/iconv.c
-+++ b/lib/util/charset/iconv.c
-@@ -31,6 +31,10 @@
- #include <unicode/utrans.h>
- #endif
-
-+#if defined(ANDROID) && (!defined(__ANDROID_API__) || __ANDROID_API__ < 28)
-+#include <byteswap.h>
-+#endif
-+
- #ifdef strcasecmp
- #undef strcasecmp
- #endif
-@@ -755,6 +755,19 @@
- return 0;
- }
-
-+#if defined(ANDROID) && (!defined(__ANDROID_API__) || __ANDROID_API__ < 28)
-+void swab(const void *from, void*to, ssize_t n)
-+{
-+ ssize_t i;
-+
-+ if (n < 0)
-+ return;
-+
-+ for (i = 0; i < (n/2)*2; i += 2)
-+ *((uint16_t*)to+i) = bswap_16(*((uint16_t*)from+i));
-+}
-+#endif
-+
- static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft,
- char **outbuf, size_t *outbytesleft)
- {
--- a/nsswitch/libwbclient/wbc_pwd.c
+++ b/nsswitch/libwbclient/wbc_pwd.c
@@ -46,7 +46,9 @@
@@ -97,14 +64,3 @@
typedef struct winbindd_gr {
fstring gr_name;
---- a/lib/replace/wscript
-+++ b/lib/replace/wscript
-@@ -225,7 +225,7 @@
- headers='sys/socket.h netinet/in.h arpa/inet.h netdb.h')
- conf.DEFINE('REPLACE_REQUIRES_LIBSOCKET_LIBNSL', 1)
-
-- conf.CHECK_FUNCS('memset_s memset_explicit')
-+ conf.undefine('HAVE_MEMSET_EXPLICIT')
-
- conf.CHECK_CODE('''
- #include <string.h>
diff --git a/tools/depends/target/samba/samba_android.patch b/tools/depends/target/samba/samba_android.patch
index 62600f71b6..0295e041f9 100644
--- a/tools/depends/target/samba/samba_android.patch
+++ b/tools/depends/target/samba/samba_android.patch
@@ -9,40 +9,6 @@
/* On Linux we lose the ability to dump core when we change our user
* ID. We know how to dump core safely, so let's make sure we have our
* dumpable flag set.
---- a/source/lib/iconv.c
-+++ b/source/lib/iconv.c
-@@ -20,7 +20,10 @@
- */
-
- #include "includes.h"
--
-+#if defined(ANDROID)
-+#include <stdint.h>
-+#include <asm/byteorder.h>
-+#endif
- /*
- * We have to use strcasecmp here as the character conversions
- * haven't been initialised yet. JRA.
-@@ -489,6 +492,19 @@
- return 0;
- }
-
-+#if defined(ANDROID)
-+void swab(const void *from, void*to, ssize_t n)
-+{
-+ ssize_t i;
-+
-+ if (n < 0)
-+ return;
-+
-+ for (i = 0; i < (n/2)*2; i += 2)
-+ *((uint16_t*)to+i) = __arch__swab16(*((uint16_t*)from+i));
-+}
-+#endif
-+
- static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft,
- char **outbuf, size_t *outbytesleft)
- {
--- a/source/lib/replace/system/passwd.h
+++ b/source/lib/replace/system/passwd.h
@@ -62,6 +62,8 @@
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 6c672b208d..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"
@@ -31,6 +32,7 @@
#include "settings/SettingsComponent.h"
#include "settings/lib/Setting.h"
#include "settings/lib/SettingDefinitions.h"
+#include "video/VideoFileItemClassify.h"
#include <stdlib.h>
#ifndef TARGET_WINDOWS
@@ -51,6 +53,7 @@
using namespace XFILE;
using namespace MEDIA_DETECT;
using namespace KODI::MESSAGING;
+using namespace KODI::VIDEO;
using namespace std::chrono_literals;
using KODI::MESSAGING::HELPERS::DialogResponse;
@@ -399,7 +402,7 @@ bool CAutorun::RunDisc(IDirectory* pDir, const std::string& strDrive, int& nAdde
for (int i = 0; i < tempItems.Size(); i++)
{
CFileItemPtr pItem = tempItems[i];
- if (!pItem->m_bIsFolder && pItem->IsVideo())
+ if (!pItem->m_bIsFolder && IsVideo(*pItem))
{
bPlaying = true;
if (pItem->IsStack())
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 239d4325ab..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"
@@ -59,14 +58,15 @@
#include "utils/log.h"
#include "video/Bookmark.h"
#include "video/VideoDatabase.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
+#include "video/VideoUtils.h"
-#include <algorithm>
#include <cstdlib>
#include <memory>
-#include <mutex>
using namespace KODI;
+using namespace KODI::VIDEO;
using namespace XFILE;
using namespace PLAYLIST;
using namespace MUSIC_INFO;
@@ -850,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();
@@ -872,51 +872,6 @@ bool CFileItem::Exists(bool bUseCache /* = true */) const
return false;
}
-bool CFileItem::IsVideo() const
-{
- /* check preset mime type */
- if(StringUtils::StartsWithNoCase(m_mimetype, "video/"))
- return true;
-
- if (HasVideoInfoTag())
- return true;
-
- if (HasGameInfoTag())
- return false;
-
- if (HasMusicInfoTag())
- return false;
-
- if (HasPictureInfoTag())
- return false;
-
- // TV recordings are videos...
- if (!m_bIsFolder && URIUtils::IsPVRTVRecordingFileOrFolder(GetPath()))
- return true;
-
- // ... all other PVR items are not.
- if (IsPVR())
- return false;
-
- if (URIUtils::IsDVD(m_strPath))
- return true;
-
- std::string extension;
- if(StringUtils::StartsWithNoCase(m_mimetype, "application/"))
- { /* check for some standard types */
- extension = m_mimetype.substr(12);
- if( StringUtils::EqualsNoCase(extension, "ogg")
- || StringUtils::EqualsNoCase(extension, "mp4")
- || StringUtils::EqualsNoCase(extension, "mxf") )
- return true;
- }
-
- //! @todo If the file is a zip file, ask the game clients if any support this
- // file before assuming it is video.
-
- return URIUtils::HasExtension(m_strPath, CServiceBroker::GetFileExtensionProvider().GetVideoExtensions());
-}
-
bool CFileItem::IsEPG() const
{
return HasEPGInfoTag();
@@ -957,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 */
@@ -1072,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");
@@ -1184,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());
@@ -1197,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
@@ -1308,19 +1213,9 @@ bool CFileItem::IsBluray() const
if (URIUtils::IsBluray(m_strPath))
return true;
- CFileItem item = CFileItem(GetOpticalMediaPath(), 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;
+ CFileItem item = CFileItem(VIDEO_UTILS::GetOpticalMediaPath(*this), false);
- return false;
+ return IsBDFile(item);
}
bool CFileItem::IsCDDA() const
@@ -1388,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());
@@ -1476,7 +1366,7 @@ void CFileItem::FillInDefaultIcon()
// audio
SetArt("icon", "DefaultAudio.png");
}
- else if ( IsVideo() )
+ else if (IsVideo(*this))
{
// video
SetArt("icon", "DefaultVideo.png");
@@ -1700,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"))
@@ -1714,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"))
@@ -1865,7 +1755,7 @@ void CFileItem::MergeInfo(const CFileItem& item)
SetLabel2(item.GetLabel2());
if (!item.GetArt().empty())
{
- if (item.IsVideo())
+ if (IsVideo(item))
AppendArt(item.GetArt());
else
SetArt(item.GetArt());
@@ -2008,37 +1898,6 @@ void CFileItem::SetFromSong(const CSong &song)
FillInMimeType(false);
}
-std::string CFileItem::GetOpticalMediaPath() const
-{
- std::string path;
- path = URIUtils::AddFileToFolder(GetPath(), "VIDEO_TS.IFO");
- if (CFile::Exists(path))
- return path;
-
- path = URIUtils::AddFileToFolder(GetPath(), "VIDEO_TS", "VIDEO_TS.IFO");
- if (CFile::Exists(path))
- return path;
-
-#ifdef HAVE_LIBBLURAY
- path = URIUtils::AddFileToFolder(GetPath(), "index.bdmv");
- if (CFile::Exists(path))
- return path;
-
- path = URIUtils::AddFileToFolder(GetPath(), "BDMV", "index.bdmv");
- if (CFile::Exists(path))
- return path;
-
- path = URIUtils::AddFileToFolder(GetPath(), "INDEX.BDM");
- if (CFile::Exists(path))
- return path;
-
- path = URIUtils::AddFileToFolder(GetPath(), "BDMV", "INDEX.BDM");
- if (CFile::Exists(path))
- return path;
-#endif
- return std::string();
-}
-
/**
* @todo Ideally this (and SetPath) would not be available outside of construction
* for CFileItem objects, or at least restricted to essentially be equivalent
@@ -2195,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 = item->GetOpticalMediaPath();
-
- 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()
@@ -3605,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
@@ -3779,7 +2561,7 @@ bool CFileItem::LoadGameTag()
bool CFileItem::LoadDetails()
{
- if (IsVideoDb())
+ if (IsVideoDb(*this))
{
if (HasVideoInfoTag())
return true;
@@ -3839,7 +2621,7 @@ bool CFileItem::LoadDetails()
return false;
}
- if (!IsPlayList() && IsVideo())
+ if (!IsPlayList() && IsVideo(*this))
{
if (HasVideoInfoTag())
return true;
@@ -3871,7 +2653,7 @@ bool CFileItem::LoadDetails()
if (playlist->Load(GetPath()) && playlist->size() == 1)
{
const auto item{(*playlist)[0]};
- if (item->IsVideo())
+ if (IsVideo(*item))
{
CVideoDatabase db;
if (!db.Open())
@@ -3959,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 7e9c2285c7..473c11c9d7 100644
--- a/xbmc/FileItem.h
+++ b/xbmc/FileItem.h
@@ -157,30 +157,12 @@ public:
bool Exists(bool bUseCache = true) const;
/*!
- \brief Check whether an item is an optical media folder or its parent.
- This will return the non-empty path to the playable entry point of the media
- one or two levels down (VIDEO_TS.IFO for DVDs or index.bdmv for BDs).
- The returned path will be empty if folder does not meet this criterion.
- \return non-empty string if item is optical media folder, empty otherwise.
- */
- std::string GetOpticalMediaPath() const;
- /*!
- \brief Check whether an item is a video item. Note that this returns true for
- anything with a video info tag, so that may include eg. folders.
- \return true if item is video, false otherwise.
- */
- bool IsVideo() 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.
\return true if item is picture, false otherwise.
*/
bool IsPicture() const;
bool IsLyrics() const;
- bool IsSubtitle() const;
/*!
\brief Check whether an item is an audio item. Note that this returns true for
@@ -214,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;
@@ -240,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;
@@ -633,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()
@@ -716,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/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp
index 3725ca1c3c..5a0c79d609 100644
--- a/xbmc/GUIInfoManager.cpp
+++ b/xbmc/GUIInfoManager.cpp
@@ -793,18 +793,6 @@ const infomap integer_bools[] = {{ "isequal", INTEGER_IS_EQUAL },
/// @skinning_v18 **[New Infolabel]** \link Player_Icon `Player.Icon`\endlink
/// <p>
/// }
-/// \table_row3{ <b>`Player.Cutlist`</b>,
-/// \anchor Player_Cutlist
-/// _string_,
-/// @return The cutlist of the currently playing item as csv in the format start1\,end1\,start2\,end2\,...
-/// Tokens must have values in the range from 0.0 to 100.0. end token must be less or equal than start token.
-/// <p>
-/// @deprecated \link Player_Cutlist `Player.Cutlist`\endlink is deprecated and will be removed in the next version.
-/// <p><hr>
-/// @skinning_v19 **[New Infolabel]** \link Player_Cutlist `Player.Cutlist`\endlink
-/// @skinning_v20 \link Player_Cutlist `Player.Cutlist`\endlink is deprecated\, use \link Player_Cuts `Player.Cuts`\endlink instead
-/// <p>
-/// }
/// \table_row3{ <b>`Player.Editlist`</b>,
/// \anchor Player_Editlist
/// _string_,
@@ -919,7 +907,6 @@ const infomap player_labels[] = {{"hasmedia", PLAYER_HAS_MEDIA},
{"hasresolutions", PLAYER_HAS_RESOLUTIONS},
{"frameadvance", PLAYER_FRAMEADVANCE},
{"icon", PLAYER_ICON},
- {"cutlist", PLAYER_CUTLIST},
{"editlist", PLAYER_EDITLIST},
{"cuts", PLAYER_CUTS},
{"scenemarkers", PLAYER_SCENE_MARKERS},
@@ -1763,14 +1750,15 @@ const infomap weather[] = {{ "isfetched", WEATHER_IS_FETCHED },
/// _string_,
/// @return Locale-specific information depending on the requested type.
/// @param type - Can be one of the following:
-/// - <b>timezonecountry</b> The country name for the current time zone.
-/// - <b>timezone</b> The full timezone name with country and optional region.
/// - <b>region</b> The currently selected region name within the selected language ( \link System_Language `System.Language` \endlink).
/// - <b>iso</b> The country code of the currently selected region as specified in <a href="https://kodi.wiki/view/Language_support#What_is_langinfo.xml">langinfo.xml</a>.
/// <p><hr>
/// @skinning_v21 **[New Infolabel]** \link System_Locale
/// `System.Locale(type)`\endlink
/// <p>
+/// @skinning_v22 **[Removed options]** `timezonecountry` and `timezone` from \link System_Locale
+/// `System.Locale(type)`\endlink
+/// <p>
/// }
/// \table_row3{ <b>`System.ProfileName`</b>,
/// \anchor System_ProfileName
@@ -9835,6 +9823,11 @@ const infomap slideshow[] = {{ "ispaused", SLIDESHOW_ISPAUSED
/// \page modules__infolabels_boolean_conditions
/// \section modules_rm_infolabels_booleans Additional revision history for Infolabels and Boolean Conditions
/// <hr>
+/// \subsection modules_rm_infolabels_booleans_v22 Kodi v22
+/// @skinning_v22 **[Removed Infolabels]** The following infolabels have been removed:
+/// - `Player.Cutlist` - Please use \link Player_Editlist `Player.EditList`\endlink for the EDL list and \link Player_Cuts `Player.Cuts`\endlink for the cut markers
+///
+/// <hr>
/// \subsection modules_rm_infolabels_booleans_v21 Kodi v21 (Omega)
/// @skinning_v21 **[Removed Infolabels]** The following infolabels have been removed:
/// - `Network.DHCPAddress` - this info did not return any meaningful value (always an empty string)
@@ -10227,15 +10220,7 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool
return AddMultiInfo(CGUIInfo(SYSTEM_IDLE_TIME, atoi(param.c_str())));
else if (prop.name == "locale")
{
- if (param == "timezonecountry")
- {
- return SYSTEM_LOCALE_TIMEZONECOUNTRY;
- }
- else if (param == "timezone")
- {
- return SYSTEM_LOCALE_TIMEZONE;
- }
- else if (param == "region")
+ if (param == "region")
{
return SYSTEM_LOCALE_REGION;
}
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 950a0cd97d..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"
@@ -37,9 +38,11 @@
#include "utils/Variant.h"
#include "utils/log.h"
#include "video/VideoDatabase.h"
+#include "video/VideoFileItemClassify.h"
using namespace PLAYLIST;
using namespace KODI::MESSAGING;
+using namespace KODI::VIDEO;
CPlayListPlayer::CPlayListPlayer(void)
{
@@ -266,7 +269,7 @@ bool CPlayListPlayer::PlayItemIdx(int itemIdx)
bool CPlayListPlayer::Play(const CFileItemPtr& pItem, const std::string& player)
{
Id playlistId;
- bool isVideo{pItem->IsVideo()};
+ bool isVideo{IsVideo(*pItem)};
bool isAudio{pItem->IsAudio()};
if (isAudio && !isVideo)
@@ -331,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);
@@ -949,7 +952,7 @@ void PLAYLIST::CPlayListPlayer::OnApplicationMessage(KODI::MESSAGING::ThreadMess
Id playlistId = TYPE_MUSIC;
for (int i = 0; i < list->Size(); i++)
{
- if ((*list)[i]->IsVideo())
+ if (IsVideo(*list->Get(i)))
{
playlistId = TYPE_VIDEO;
break;
@@ -967,7 +970,7 @@ void PLAYLIST::CPlayListPlayer::OnApplicationMessage(KODI::MESSAGING::ThreadMess
{
return;
}
- if (item->IsAudio() || item->IsVideo())
+ if (item->IsAudio() || IsVideo(*item))
Play(item, pMsg->strParam);
else
g_application.PlayMedia(*item, pMsg->strParam, playlistId);
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/Util.cpp b/xbmc/Util.cpp
index a4ee52645c..dea659099c 100644
--- a/xbmc/Util.cpp
+++ b/xbmc/Util.cpp
@@ -7,6 +7,7 @@
*/
#include "network/Network.h"
+#include "video/VideoFileItemClassify.h"
#if defined(TARGET_DARWIN)
#include <sys/param.h>
#include <mach-o/dyld.h>
@@ -92,6 +93,7 @@ using namespace MEDIA_DETECT;
using namespace XFILE;
using namespace PLAYLIST;
using KODI::UTILITY::CDigest;
+using namespace KODI::VIDEO;
#if !defined(TARGET_WINDOWS)
unsigned int CUtil::s_randomSeed = time(NULL);
@@ -2054,10 +2056,8 @@ void CUtil::ScanForExternalSubtitles(const std::string& strMovie, std::vector<st
auto start = std::chrono::steady_clock::now();
CFileItem item(strMovie, false);
- if ((item.IsInternetStream() && !URIUtils::IsOnLAN(item.GetDynPath()))
- || item.IsPlayList()
- || item.IsLiveTV()
- || !item.IsVideo())
+ if ((item.IsInternetStream() && !URIUtils::IsOnLAN(item.GetDynPath())) || item.IsPlayList() ||
+ item.IsLiveTV() || !IsVideo(item))
return;
CLog::Log(LOGDEBUG, "{}: Searching for subtitles...", __FUNCTION__);
@@ -2346,11 +2346,8 @@ std::string CUtil::GetVobSubIdxFromSub(const std::string& vobSub)
void CUtil::ScanForExternalAudio(const std::string& videoPath, std::vector<std::string>& vecAudio)
{
CFileItem item(videoPath, false);
- if ( item.IsInternetStream()
- || item.IsPlayList()
- || item.IsLiveTV()
- || item.IsPVR()
- || !item.IsVideo())
+ if (item.IsInternetStream() || item.IsPlayList() || item.IsLiveTV() || item.IsPVR() ||
+ !IsVideo(item))
return;
std::string strBasePath;
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 3413a18c4c..6541a22759 100644
--- a/xbmc/application/Application.cpp
+++ b/xbmc/application/Application.cpp
@@ -60,6 +60,7 @@
#include "filesystem/DirectoryFactory.h"
#include "filesystem/DllLibCurl.h"
#include "filesystem/File.h"
+#include "video/VideoFileItemClassify.h"
#ifdef HAS_FILESYSTEM_NFS
#include "filesystem/NFSFile.h"
#endif
@@ -198,6 +199,7 @@ using namespace PVR;
using namespace PERIPHERALS;
using namespace KODI;
using namespace KODI::MESSAGING;
+using namespace KODI::VIDEO;
using namespace ActiveAE;
using namespace XbmcThreads;
@@ -2301,11 +2303,11 @@ bool CApplication::PlayFile(CFileItem item, const std::string& player, bool bRes
m_nextPlaylistItem = -1;
stackHelper->Clear();
- if (item.IsVideo())
+ if (IsVideo(item))
CUtil::ClearSubtitles();
}
- if (item.IsDiscStub())
+ if (IsDiscStub(item))
{
return CServiceBroker::GetMediaManager().playStubFile(item);
}
@@ -2346,7 +2348,7 @@ bool CApplication::PlayFile(CFileItem item, const std::string& player, bool bRes
{
// the following code block is only applicable when bRestart is false OR to ISO stacks
- if (item.IsVideo())
+ if (IsVideo(item))
{
// open the d/b and retrieve the bookmarks for the current movie
CVideoDatabase dbs;
@@ -2354,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,
@@ -2424,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 = [&]()
@@ -2458,7 +2460,7 @@ bool CApplication::PlayFile(CFileItem item, const std::string& player, bool bRes
CSettings::SETTING_MUSICFILES_SELECTACTION) &&
!CMediaSettings::GetInstance().DoesMediaStartWindowed();
}
- else if (item.IsVideo() && playlistId == PLAYLIST::TYPE_VIDEO &&
+ else if (IsVideo(item) && playlistId == PLAYLIST::TYPE_VIDEO &&
CServiceBroker::GetPlaylistPlayer().GetPlaylist(playlistId).size() > 1)
{ // playing from a playlist by the looks
// don't switch to fullscreen if we are not playing the first item...
@@ -2783,9 +2785,9 @@ bool CApplication::OnMessage(CGUIMessage& message)
bool bNothingToQueue = false;
const auto appPlayer = GetComponent<CApplicationPlayer>();
- if (!file.IsVideo() && appPlayer->IsPlayingVideo())
+ if (!IsVideo(file) && appPlayer->IsPlayingVideo())
bNothingToQueue = true;
- else if ((!file.IsAudio() || file.IsVideo()) && appPlayer->IsPlayingAudio())
+ else if ((!file.IsAudio() || IsVideo(file)) && appPlayer->IsPlayingAudio())
bNothingToQueue = true;
if (bNothingToQueue)
@@ -3053,7 +3055,7 @@ bool CApplication::ExecuteXBMCAction(std::string actionStr,
}
else
#endif
- if (item.IsAudio() || item.IsVideo() || item.IsGame())
+ if (item.IsAudio() || IsVideo(item) || item.IsGame())
{ // an audio or video file
PlayFile(item, "");
}
@@ -3174,10 +3176,8 @@ void CApplication::ProcessSlow()
// Temporarily pause pausable jobs when viewing video/picture
int currentWindow = CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow();
- if (CurrentFileItem().IsVideo() ||
- CurrentFileItem().IsPicture() ||
- currentWindow == WINDOW_FULLSCREEN_VIDEO ||
- currentWindow == WINDOW_FULLSCREEN_GAME ||
+ if (IsVideo(CurrentFileItem()) || CurrentFileItem().IsPicture() ||
+ currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_FULLSCREEN_GAME ||
currentWindow == WINDOW_SLIDESHOW)
{
CServiceBroker::GetJobManager()->PauseJobs();
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 ed36a27e18..637f67ddcc 100644
--- a/xbmc/application/ApplicationPlayerCallback.cpp
+++ b/xbmc/application/ApplicationPlayerCallback.cpp
@@ -32,10 +32,13 @@
#include "utils/URIUtils.h"
#include "utils/log.h"
#include "video/VideoDatabase.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
#include <memory>
+using namespace KODI::VIDEO;
+
CApplicationPlayerCallback::CApplicationPlayerCallback()
{
}
@@ -54,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 =
@@ -80,7 +83,7 @@ void CApplicationPlayerCallback::OnPlayBackStarted(const CFileItem& file)
* This should speed up player startup for files on internet filesystems (eg. webdav) and
* increase performance on low powered systems (Atom/ARM).
*/
- if (file.IsVideo() || file.IsGame())
+ if (IsVideo(file) || file.IsGame())
{
CServiceBroker::GetJobManager()->PauseJobs();
}
@@ -128,7 +131,7 @@ void CApplicationPlayerCallback::OnPlayerCloseFile(const CFileItem& file,
if ((fileItem.IsAudio() && advancedSettings->m_audioPlayCountMinimumPercent > 0 &&
percent >= advancedSettings->m_audioPlayCountMinimumPercent) ||
- (fileItem.IsVideo() && advancedSettings->m_videoPlayCountMinimumPercent > 0 &&
+ (IsVideo(fileItem) && advancedSettings->m_videoPlayCountMinimumPercent > 0 &&
percent >= advancedSettings->m_videoPlayCountMinimumPercent))
{
playCountUpdate = true;
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/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
index 908b087b98..528822ddbb 100644
--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
@@ -1313,7 +1313,7 @@ void CActiveAE::Configure(AEAudioFormat *desiredFmt)
format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_AC3;
format.m_streamInfo.m_channels = 2;
format.m_streamInfo.m_sampleRate = 48000;
- format.m_streamInfo.m_ac3FrameSize = m_encoderFormat.m_frames;
+ format.m_streamInfo.m_frameSize = m_encoderFormat.m_frames;
//! @todo implement
if (m_encoderBuffers && initSink)
{
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/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp
index 6da358f792..e0a42c62a4 100644
--- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp
@@ -162,7 +162,8 @@ int CAESinkAUDIOTRACK::AudioTrackWrite(char* audioData, int offsetInBytes, int s
if (m_floatbuf.size() != (sizeInBytes - offsetInBytes) / sizeof(float))
m_floatbuf.resize((sizeInBytes - offsetInBytes) / sizeof(float));
memcpy(m_floatbuf.data(), audioData + offsetInBytes, sizeInBytes - offsetInBytes);
- written = m_at_jni->write(m_floatbuf, 0, (sizeInBytes - offsetInBytes) / sizeof(float), CJNIAudioTrack::WRITE_BLOCKING);
+ written = m_at_jni->write(m_floatbuf, 0, (sizeInBytes - offsetInBytes) / sizeof(float),
+ CJNIAudioTrack::WRITE_BLOCKING);
written *= sizeof(float);
}
else if (m_jniAudioFormat == CJNIAudioFormat::ENCODING_IEC61937)
@@ -170,10 +171,8 @@ int CAESinkAUDIOTRACK::AudioTrackWrite(char* audioData, int offsetInBytes, int s
if (m_shortbuf.size() != (sizeInBytes - offsetInBytes) / sizeof(int16_t))
m_shortbuf.resize((sizeInBytes - offsetInBytes) / sizeof(int16_t));
memcpy(m_shortbuf.data(), audioData + offsetInBytes, sizeInBytes - offsetInBytes);
- if (CJNIBase::GetSDKVersion() >= 23)
- written = m_at_jni->write(m_shortbuf, 0, (sizeInBytes - offsetInBytes) / sizeof(int16_t), CJNIAudioTrack::WRITE_BLOCKING);
- else
- written = m_at_jni->write(m_shortbuf, 0, (sizeInBytes - offsetInBytes) / sizeof(int16_t));
+ written = m_at_jni->write(m_shortbuf, 0, (sizeInBytes - offsetInBytes) / sizeof(int16_t),
+ CJNIAudioTrack::WRITE_BLOCKING);
written *= sizeof(uint16_t);
}
else
@@ -181,10 +180,8 @@ int CAESinkAUDIOTRACK::AudioTrackWrite(char* audioData, int offsetInBytes, int s
if (static_cast<int>(m_charbuf.size()) != (sizeInBytes - offsetInBytes))
m_charbuf.resize(sizeInBytes - offsetInBytes);
memcpy(m_charbuf.data(), audioData + offsetInBytes, sizeInBytes - offsetInBytes);
- if (CJNIBase::GetSDKVersion() >= 23)
- written = m_at_jni->write(m_charbuf, 0, sizeInBytes - offsetInBytes, CJNIAudioTrack::WRITE_BLOCKING);
- else
- written = m_at_jni->write(m_charbuf, 0, sizeInBytes - offsetInBytes);
+ written =
+ m_at_jni->write(m_charbuf, 0, sizeInBytes - offsetInBytes, CJNIAudioTrack::WRITE_BLOCKING);
}
return written;
@@ -461,15 +458,15 @@ bool CAESinkAUDIOTRACK::Initialize(AEAudioFormat &format, std::string &device)
rawlength_in_seconds = 8 * m_format.m_streamInfo.GetDuration() / 1000;
break;
case CAEStreamInfo::STREAM_TYPE_AC3:
- ac3FrameSize = m_format.m_streamInfo.m_ac3FrameSize;
- if (ac3FrameSize == 0)
- ac3FrameSize = 1536; // fallback if not set, e.g. Transcoding
- m_min_buffer_size = std::max(m_min_buffer_size * 3, ac3FrameSize * 8);
- m_format.m_frames = m_min_buffer_size;
- multiplier = m_min_buffer_size / ac3FrameSize; // int division is wanted
- rawlength_in_seconds = multiplier * m_format.m_streamInfo.GetDuration() / 1000;
+ ac3FrameSize = m_format.m_streamInfo.m_frameSize;
+ if (ac3FrameSize == 0)
+ ac3FrameSize = 1536; // fallback if not set, e.g. Transcoding
+ m_min_buffer_size = std::max(m_min_buffer_size * 3, ac3FrameSize * 8);
+ m_format.m_frames = m_min_buffer_size;
+ multiplier = m_min_buffer_size / ac3FrameSize; // int division is wanted
+ rawlength_in_seconds = multiplier * m_format.m_streamInfo.GetDuration() / 1000;
break;
- // EAC3 is currently not supported
+ // EAC3 is currently not supported
case CAEStreamInfo::STREAM_TYPE_EAC3:
m_min_buffer_size = 2 * 10752; // least common multiple of 1792 and 1536
m_format.m_frames = m_min_buffer_size; // needs testing
@@ -1119,26 +1116,23 @@ void CAESinkAUDIOTRACK::UpdateAvailablePassthroughCapabilities(bool isRaw)
}
}
- if (CJNIAudioManager::GetSDKVersion() >= 23)
+ if (CJNIAudioFormat::ENCODING_DTS_HD != -1)
{
- if (CJNIAudioFormat::ENCODING_DTS_HD != -1)
+ if (VerifySinkConfiguration(48000, AEChannelMapToAUDIOTRACKChannelMask(AE_CH_LAYOUT_7_1),
+ CJNIAudioFormat::ENCODING_DTS_HD, true))
{
- if (VerifySinkConfiguration(48000, AEChannelMapToAUDIOTRACKChannelMask(AE_CH_LAYOUT_7_1),
- CJNIAudioFormat::ENCODING_DTS_HD, true))
- {
- CLog::Log(LOGDEBUG, "Firmware implements DTS-HD RAW");
- m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_DTSHD);
- m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_DTSHD_MA);
- }
+ CLog::Log(LOGDEBUG, "Firmware implements DTS-HD RAW");
+ m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_DTSHD);
+ m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_DTSHD_MA);
}
- if (CJNIAudioFormat::ENCODING_DOLBY_TRUEHD != -1)
+ }
+ if (CJNIAudioFormat::ENCODING_DOLBY_TRUEHD != -1)
+ {
+ if (VerifySinkConfiguration(48000, AEChannelMapToAUDIOTRACKChannelMask(AE_CH_LAYOUT_7_1),
+ CJNIAudioFormat::ENCODING_DOLBY_TRUEHD, true))
{
- if (VerifySinkConfiguration(48000, AEChannelMapToAUDIOTRACKChannelMask(AE_CH_LAYOUT_7_1),
- CJNIAudioFormat::ENCODING_DOLBY_TRUEHD, true))
- {
- CLog::Log(LOGDEBUG, "Firmware implements TrueHD RAW");
- m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_TRUEHD);
- }
+ CLog::Log(LOGDEBUG, "Firmware implements TrueHD RAW");
+ m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_TRUEHD);
}
}
}
@@ -1200,10 +1194,9 @@ void CAESinkAUDIOTRACK::UpdateAvailablePCMCapabilities()
int encoding = CJNIAudioFormat::ENCODING_PCM_16BIT;
m_sinkSupportsFloat = VerifySinkConfiguration(native_sampleRate, CJNIAudioFormat::CHANNEL_OUT_STEREO, CJNIAudioFormat::ENCODING_PCM_FLOAT);
- if (CJNIAudioManager::GetSDKVersion() >= 21)
- m_sinkSupportsMultiChannelFloat =
- VerifySinkConfiguration(native_sampleRate, CJNIAudioFormat::CHANNEL_OUT_7POINT1_SURROUND,
- CJNIAudioFormat::ENCODING_PCM_FLOAT);
+ m_sinkSupportsMultiChannelFloat =
+ VerifySinkConfiguration(native_sampleRate, CJNIAudioFormat::CHANNEL_OUT_7POINT1_SURROUND,
+ CJNIAudioFormat::ENCODING_PCM_FLOAT);
if (m_sinkSupportsFloat)
{
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDARWINTVOS.mm b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINTVOS.mm
index 5d66474ca0..162b5c9650 100644
--- a/xbmc/cores/AudioEngine/Sinks/AESinkDARWINTVOS.mm
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINTVOS.mm
@@ -784,15 +784,15 @@ bool CAESinkDARWINTVOS::Initialize(AEAudioFormat& format, std::string& device)
switch (format.m_streamInfo.m_type)
{
case CAEStreamInfo::STREAM_TYPE_AC3:
- if (!format.m_streamInfo.m_ac3FrameSize)
- format.m_streamInfo.m_ac3FrameSize = 1536;
- format.m_frames = format.m_streamInfo.m_ac3FrameSize;
+ if (!format.m_streamInfo.m_frameSize)
+ format.m_streamInfo.m_frameSize = 1536;
+ format.m_frames = format.m_streamInfo.m_frameSize;
buffer_size = format.m_frames * 8;
break;
case CAEStreamInfo::STREAM_TYPE_EAC3:
- if (!format.m_streamInfo.m_ac3FrameSize)
- format.m_streamInfo.m_ac3FrameSize = 1536;
- format.m_frames = format.m_streamInfo.m_ac3FrameSize;
+ if (!format.m_streamInfo.m_frameSize)
+ format.m_streamInfo.m_frameSize = 1536;
+ format.m_frames = format.m_streamInfo.m_frameSize;
buffer_size = format.m_frames * 8;
break;
case CAEStreamInfo::STREAM_TYPE_DTS_512:
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/AudioEngine/Sinks/AESinkStarfish.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkStarfish.cpp
index 0d07b44fa3..d9c8859cc4 100644
--- a/xbmc/cores/AudioEngine/Sinks/AESinkStarfish.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkStarfish.cpp
@@ -21,10 +21,17 @@ namespace
{
constexpr unsigned int STARFISH_AUDIO_BUFFERS = 8;
constexpr unsigned int AC3_SYNCFRAME_SIZE = 2560;
+constexpr unsigned int DTDHD_MA_MIN_SYNCFRAME_SIZE = 2012 + 2764;
static constexpr auto ms_audioCodecMap = make_map<CAEStreamInfo::DataType, std::string_view>({
{CAEStreamInfo::STREAM_TYPE_AC3, "AC3"},
{CAEStreamInfo::STREAM_TYPE_EAC3, "AC3 PLUS"},
+ {CAEStreamInfo::STREAM_TYPE_DTS_512, "DTS"},
+ {CAEStreamInfo::STREAM_TYPE_DTS_1024, "DTS"},
+ {CAEStreamInfo::STREAM_TYPE_DTS_2048, "DTS"},
+ {CAEStreamInfo::STREAM_TYPE_DTSHD, "DTS"},
+ {CAEStreamInfo::STREAM_TYPE_DTSHD_CORE, "DTS"},
+ {CAEStreamInfo::STREAM_TYPE_DTSHD_MA, "DTS"},
});
} // namespace
@@ -63,6 +70,12 @@ void CAESinkStarfish::EnumerateDevicesEx(AEDeviceInfoList& list, bool force)
info.m_deviceType = AE_DEVTYPE_IEC958;
info.m_streamTypes.emplace_back(CAEStreamInfo::STREAM_TYPE_AC3);
info.m_streamTypes.emplace_back(CAEStreamInfo::STREAM_TYPE_EAC3);
+ info.m_streamTypes.emplace_back(CAEStreamInfo::STREAM_TYPE_DTS_512);
+ info.m_streamTypes.emplace_back(CAEStreamInfo::STREAM_TYPE_DTS_1024);
+ info.m_streamTypes.emplace_back(CAEStreamInfo::STREAM_TYPE_DTS_2048);
+ info.m_streamTypes.emplace_back(CAEStreamInfo::STREAM_TYPE_DTSHD);
+ info.m_streamTypes.emplace_back(CAEStreamInfo::STREAM_TYPE_DTSHD_CORE);
+ info.m_streamTypes.emplace_back(CAEStreamInfo::STREAM_TYPE_DTSHD_MA);
info.m_sampleRates.emplace_back(32000);
info.m_sampleRates.emplace_back(44100);
@@ -89,8 +102,6 @@ bool CAESinkStarfish::Initialize(AEAudioFormat& format, std::string& device)
}
m_format.m_frameSize = 1;
- format = m_format;
-
CVariant payload;
payload["isAudioOnly"] = true;
payload["mediaTransportType"] = "BUFFERSTREAM";
@@ -107,10 +118,10 @@ bool CAESinkStarfish::Initialize(AEAudioFormat& format, std::string& device)
{
case CAEStreamInfo::STREAM_TYPE_AC3:
{
- if (!format.m_streamInfo.m_ac3FrameSize)
- format.m_streamInfo.m_ac3FrameSize = AC3_SYNCFRAME_SIZE;
- format.m_frames = format.m_streamInfo.m_ac3FrameSize;
- m_bufferSize = format.m_frames * STARFISH_AUDIO_BUFFERS;
+ if (!m_format.m_streamInfo.m_frameSize)
+ m_format.m_streamInfo.m_frameSize = AC3_SYNCFRAME_SIZE;
+ m_format.m_frames = m_format.m_streamInfo.m_frameSize;
+ m_bufferSize = m_format.m_frames * STARFISH_AUDIO_BUFFERS;
break;
}
case CAEStreamInfo::STREAM_TYPE_EAC3:
@@ -119,10 +130,30 @@ bool CAESinkStarfish::Initialize(AEAudioFormat& format, std::string& device)
payload["option"]["externalStreamingInfo"]["contents"]["ac3PlusInfo"]["frequency"] =
static_cast<double>(m_format.m_streamInfo.m_sampleRate) / 1000;
- if (!format.m_streamInfo.m_ac3FrameSize)
- format.m_streamInfo.m_ac3FrameSize = AC3_SYNCFRAME_SIZE;
- format.m_frames = format.m_streamInfo.m_ac3FrameSize;
- m_bufferSize = format.m_frames * STARFISH_AUDIO_BUFFERS;
+ if (!m_format.m_streamInfo.m_frameSize)
+ m_format.m_streamInfo.m_frameSize = AC3_SYNCFRAME_SIZE;
+ m_format.m_frames = m_format.m_streamInfo.m_frameSize;
+ m_bufferSize = m_format.m_frames * STARFISH_AUDIO_BUFFERS;
+ break;
+ }
+ case CAEStreamInfo::STREAM_TYPE_DTSHD_CORE:
+ case CAEStreamInfo::STREAM_TYPE_DTS_512:
+ case CAEStreamInfo::STREAM_TYPE_DTS_1024:
+ case CAEStreamInfo::STREAM_TYPE_DTS_2048:
+ case CAEStreamInfo::STREAM_TYPE_DTSHD:
+ case CAEStreamInfo::STREAM_TYPE_DTSHD_MA:
+ {
+ payload["option"]["externalStreamingInfo"]["contents"]["dtsInfo"]["channels"] =
+ m_format.m_streamInfo.m_channels;
+ payload["option"]["externalStreamingInfo"]["contents"]["dtsInfo"]["frequency"] =
+ static_cast<double>(m_format.m_streamInfo.m_sampleRate) / 1000;
+
+ m_format.m_frames = m_format.m_streamInfo.m_frameSize;
+
+ // DTSHD_MA has dynamic frame sizes but we need to ensure that the buffer is large enough
+ if (m_format.m_streamInfo.m_type == CAEStreamInfo::STREAM_TYPE_DTSHD_MA)
+ m_format.m_frames = DTDHD_MA_MIN_SYNCFRAME_SIZE * 2 - 1;
+ m_bufferSize = m_format.m_frames * STARFISH_AUDIO_BUFFERS;
break;
}
default:
@@ -140,7 +171,7 @@ bool CAESinkStarfish::Initialize(AEAudioFormat& format, std::string& device)
m_bufferSize;
// Internal buffer?
payload["option"]["externalStreamingInfo"]["bufferingCtrInfo"]["srcBufferLevelAudio"]["minimum"] =
- format.m_frames;
+ m_format.m_frames;
payload["option"]["externalStreamingInfo"]["bufferingCtrInfo"]["srcBufferLevelAudio"]["maximum"] =
m_bufferSize;
@@ -159,6 +190,8 @@ bool CAESinkStarfish::Initialize(AEAudioFormat& format, std::string& device)
return false;
}
+ format = m_format;
+
return true;
}
diff --git a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp
index b045a19d10..359cd26b4e 100644
--- a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp
+++ b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp
@@ -369,7 +369,7 @@ bool CAEStreamParser::TrySyncAC3(uint8_t* data,
// no need to resync => return true
return true;
}
- m_info.m_ac3FrameSize = fsizeMain;
+ m_info.m_frameSize = fsizeMain;
if (TrySyncAC3(data + fsizeMain, size - fsizeMain, resyncing, true))
{
// concatenate the main and dependent frames
@@ -393,7 +393,7 @@ bool CAEStreamParser::TrySyncAC3(uint8_t* data,
m_info.m_channels = AC3Channels[acmod] + lfeon;
m_syncFunc = &CAEStreamParser::SyncAC3;
m_info.m_type = CAEStreamInfo::STREAM_TYPE_AC3;
- m_info.m_ac3FrameSize += m_fsize;
+ m_info.m_frameSize += m_fsize;
m_info.m_repeat = 1;
CLog::Log(LOGINFO, "CAEStreamParser::TrySyncAC3 - AC3 stream detected ({} channels, {}Hz)",
@@ -452,7 +452,7 @@ bool CAEStreamParser::TrySyncAC3(uint8_t* data,
// no need to resync => return true
return true;
}
- m_info.m_ac3FrameSize = fsizeMain;
+ m_info.m_frameSize = fsizeMain;
if (TrySyncAC3(data + fsizeMain, size - fsizeMain, resyncing, true))
{
// concatenate the main and dependent frames
@@ -469,7 +469,7 @@ bool CAEStreamParser::TrySyncAC3(uint8_t* data,
m_info.m_channels = AC3Channels[acmod] + lfeon;
m_syncFunc = &CAEStreamParser::SyncAC3;
m_info.m_type = CAEStreamInfo::STREAM_TYPE_EAC3;
- m_info.m_ac3FrameSize += m_fsize;
+ m_info.m_frameSize += m_fsize;
CLog::Log(LOGINFO, "CAEStreamParser::TrySyncAC3 - E-AC3 stream detected ({} channels, {}Hz)",
m_info.m_channels, m_info.m_sampleRate);
@@ -673,6 +673,7 @@ unsigned int CAEStreamParser::SyncDTS(uint8_t* data, unsigned int size)
m_dtsBlocks = dtsBlocks;
m_info.m_channels = DTSChannels[amode] + (lfe ? 1 : 0);
m_syncFunc = &CAEStreamParser::SyncDTS;
+ m_info.m_frameSize = m_fsize;
m_info.m_repeat = 1;
if (dataType == CAEStreamInfo::STREAM_TYPE_DTSHD_MA)
@@ -812,6 +813,7 @@ unsigned int CAEStreamParser::SyncTrueHD(uint8_t* data, unsigned int size)
m_fsize = length;
m_info.m_type = CAEStreamInfo::STREAM_TYPE_TRUEHD;
m_syncFunc = &CAEStreamParser::SyncTrueHD;
+ m_info.m_frameSize = length;
m_info.m_repeat = 1;
return skip;
}
diff --git a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h
index dff809d137..acfa77d987 100644
--- a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h
+++ b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h
@@ -45,7 +45,7 @@ public:
bool m_dataIsLE = true;
unsigned int m_dtsPeriod = 0;
unsigned int m_repeat = 0;
- unsigned int m_ac3FrameSize = 0;
+ unsigned int m_frameSize = 0;
};
class CAEStreamParser
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/DllLoader/exports/wrapper.c b/xbmc/cores/DllLoader/exports/wrapper.c
index 0d3d54bc1d..455ec0b8ca 100644
--- a/xbmc/cores/DllLoader/exports/wrapper.c
+++ b/xbmc/cores/DllLoader/exports/wrapper.c
@@ -36,7 +36,6 @@ typedef fpos_t fpos64_t;
#endif
struct mntent;
-struct statvfs64;
void* dllmalloc(size_t );
void* dllcalloc( size_t , size_t );
@@ -92,7 +91,6 @@ int dll_ftrylockfile(FILE *file);
void dll_funlockfile(FILE *file);
int dll_fstat64(int fd, struct stat64 *buf);
int dll_fstat(int fd, struct _stat *buf);
-int dll_fstatvfs64(int fildes, struct statvfs64 *buf);
FILE* dll_popen(const char *command, const char *mode);
void* dll_dlopen(const char *filename, int flag);
int dll_setvbuf(FILE *stream, char *buf, int type, size_t size);
@@ -445,11 +443,6 @@ int __wrap_fstat64(int fd, struct stat64* buf)
return dll_fstat64(fd, buf);
}
-int __wrap_fstatvfs64(int fd, struct statvfs64* buf)
-{
- return dll_fstatvfs64(fd, buf);
-}
-
int __wrap_setvbuf(FILE *stream, char *buf, int type, size_t size)
{
return dll_setvbuf(stream, buf, type, size);
diff --git a/xbmc/cores/DllLoader/exports/wrapper_mach_alias b/xbmc/cores/DllLoader/exports/wrapper_mach_alias
index 88ff67554f..dfee67eefd 100644
--- a/xbmc/cores/DllLoader/exports/wrapper_mach_alias
+++ b/xbmc/cores/DllLoader/exports/wrapper_mach_alias
@@ -20,7 +20,6 @@ ___wrap_fread _fread
___wrap_freopen _freopen
___wrap_fseek _fseek
___wrap_fsetpos _fsetpos
-___wrap_fstatvfs64 _fstatvfs64
___wrap_ftell _ftell
___wrap_ftrylockfile _ftrylockfile
___wrap_funlockfile _funlockfile
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/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp
index c83d263968..ce6de6f20d 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp
@@ -353,14 +353,10 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio
CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Open - {}", "null size, cannot handle");
goto FAIL;
}
- else if (hints.orientation && m_render_surface && CJNIBase::GetSDKVersion() < 23)
- {
- CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Open - {}",
- "Surface does not support orientation before API 23");
- goto FAIL;
- }
- else if (!CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_VIDEOPLAYER_USEMEDIACODEC) &&
- !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_VIDEOPLAYER_USEMEDIACODECSURFACE))
+ else if (!CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
+ CSettings::SETTING_VIDEOPLAYER_USEMEDIACODEC) &&
+ !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
+ CSettings::SETTING_VIDEOPLAYER_USEMEDIACODECSURFACE))
goto FAIL;
CLog::Log(
@@ -553,44 +549,41 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio
m_formatname = isDvhe ? "amc-dvhe" : "amc-dvh1";
profile = 0; // not an HEVC profile
- if (CJNIBase::GetSDKVersion() >= 24)
+ switch (m_hints.dovi.dv_profile)
{
- switch (m_hints.dovi.dv_profile)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 6:
- // obsolete profiles that are not supported in current applications.
- // 0 is ignored in case the AVDOVIDecoderConfigurationRecord hint is unset.
- break;
- case 4:
- profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvheDtr;
- break;
- case 5:
- profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvheStn;
- break;
- case 7:
- // set profile 8 when converting
- if (convertDovi && CJNIBase::GetSDKVersion() >= 27)
- profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvheSt;
-
- // Profile 7 is not commonly supported. Not setting the profile here
- // allows to pick the first available Dolby Vision codec.
- // profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvheDtb;
- break;
- case 8:
- if (CJNIBase::GetSDKVersion() >= 27)
- profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvheSt;
- break;
- case 9:
- if (CJNIBase::GetSDKVersion() >= 27)
- profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvavSe;
- break;
- default:
- break;
- }
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 6:
+ // obsolete profiles that are not supported in current applications.
+ // 0 is ignored in case the AVDOVIDecoderConfigurationRecord hint is unset.
+ break;
+ case 4:
+ profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvheDtr;
+ break;
+ case 5:
+ profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvheStn;
+ break;
+ case 7:
+ // set profile 8 when converting
+ if (convertDovi && CJNIBase::GetSDKVersion() >= 27)
+ profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvheSt;
+
+ // Profile 7 is not commonly supported. Not setting the profile here
+ // allows to pick the first available Dolby Vision codec.
+ // profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvheDtb;
+ break;
+ case 8:
+ if (CJNIBase::GetSDKVersion() >= 27)
+ profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvheSt;
+ break;
+ case 9:
+ if (CJNIBase::GetSDKVersion() >= 27)
+ profile = CJNIMediaCodecInfoCodecProfileLevel::DolbyVisionProfileDvavSe;
+ break;
+ default:
+ break;
}
}
}
@@ -1389,7 +1382,8 @@ void CDVDVideoCodecAndroidMediaCodec::SignalEndOfStream()
{
xbmc_jnienv()->ExceptionDescribe();
xbmc_jnienv()->ExceptionClear();
- CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::{}: queueInputBuffer failed");
+ CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::{}: queueInputBuffer failed",
+ __func__);
}
else
{
@@ -1476,7 +1470,7 @@ bool CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec(void)
CJNIMediaFormat::createVideoFormat(m_mime, m_hints.width, m_hints.height);
mediaformat.setInteger(CJNIMediaFormat::KEY_MAX_INPUT_SIZE, 0);
- if (CJNIBase::GetSDKVersion() >= 23 && m_render_surface)
+ if (m_render_surface)
{
// Handle rotation
mediaformat.setInteger(CJNIMediaFormat::KEY_ROTATION, m_hints.orientation);
@@ -1487,89 +1481,86 @@ bool CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec(void)
true);
}
- if (CJNIBase::GetSDKVersion() >= 24)
+ switch (m_hints.colorRange)
{
- switch (m_hints.colorRange)
- {
- case AVCOL_RANGE_UNSPECIFIED:
- CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Color range: "
- "AVCOL_RANGE_UNSPECIFIED");
- break;
- case AVCOL_RANGE_MPEG:
- mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_RANGE,
- CJNIMediaFormat::COLOR_RANGE_LIMITED);
- break;
- case AVCOL_RANGE_JPEG:
- mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_RANGE, CJNIMediaFormat::COLOR_RANGE_FULL);
- break;
- default:
- CLog::Log(LOGWARNING,
- "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Unhandled Color range: {}",
- m_hints.colorRange);
- break;
- }
+ case AVCOL_RANGE_UNSPECIFIED:
+ CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Color range: "
+ "AVCOL_RANGE_UNSPECIFIED");
+ break;
+ case AVCOL_RANGE_MPEG:
+ mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_RANGE,
+ CJNIMediaFormat::COLOR_RANGE_LIMITED);
+ break;
+ case AVCOL_RANGE_JPEG:
+ mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_RANGE, CJNIMediaFormat::COLOR_RANGE_FULL);
+ break;
+ default:
+ CLog::Log(LOGWARNING,
+ "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Unhandled Color range: {}",
+ m_hints.colorRange);
+ break;
+ }
- switch (m_hints.colorPrimaries)
- {
- case AVCOL_PRI_UNSPECIFIED:
- CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Color primaries: "
- "AVCOL_PRI_UNSPECIFIED");
- break;
- case AVCOL_PRI_BT709:
- mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_STANDARD,
- CJNIMediaFormat::COLOR_STANDARD_BT709);
- break;
- case AVCOL_PRI_BT2020:
- mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_STANDARD,
- CJNIMediaFormat::COLOR_STANDARD_BT2020);
- break;
- default:
- CLog::Log(
- LOGWARNING,
- "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Unhandled Color primaries: {}",
- m_hints.colorPrimaries);
- break;
- }
+ switch (m_hints.colorPrimaries)
+ {
+ case AVCOL_PRI_UNSPECIFIED:
+ CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Color primaries: "
+ "AVCOL_PRI_UNSPECIFIED");
+ break;
+ case AVCOL_PRI_BT709:
+ mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_STANDARD,
+ CJNIMediaFormat::COLOR_STANDARD_BT709);
+ break;
+ case AVCOL_PRI_BT2020:
+ mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_STANDARD,
+ CJNIMediaFormat::COLOR_STANDARD_BT2020);
+ break;
+ default:
+ CLog::Log(
+ LOGWARNING,
+ "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Unhandled Color primaries: {}",
+ m_hints.colorPrimaries);
+ break;
+ }
- switch (m_hints.colorTransferCharacteristic)
- {
- case AVCOL_TRC_UNSPECIFIED:
- CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Transfer "
- "characteristic: AVCOL_TRC_UNSPECIFIED");
- break;
- case AVCOL_TRC_LINEAR:
- mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_TRANSFER,
- CJNIMediaFormat::COLOR_TRANSFER_LINEAR);
- break;
- case AVCOL_TRC_BT709:
- case AVCOL_TRC_SMPTE170M:
- mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_TRANSFER,
- CJNIMediaFormat::COLOR_TRANSFER_SDR_VIDEO);
- break;
- case AVCOL_TRC_SMPTE2084:
- mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_TRANSFER,
- CJNIMediaFormat::COLOR_TRANSFER_ST2084);
- break;
- case AVCOL_TRC_ARIB_STD_B67:
- mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_TRANSFER,
- CJNIMediaFormat::COLOR_TRANSFER_HLG);
- break;
- default:
- CLog::Log(LOGWARNING,
- "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Unhandled Transfer "
- "characteristic: {}",
- m_hints.colorTransferCharacteristic);
- break;
- }
+ switch (m_hints.colorTransferCharacteristic)
+ {
+ case AVCOL_TRC_UNSPECIFIED:
+ CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Transfer "
+ "characteristic: AVCOL_TRC_UNSPECIFIED");
+ break;
+ case AVCOL_TRC_LINEAR:
+ mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_TRANSFER,
+ CJNIMediaFormat::COLOR_TRANSFER_LINEAR);
+ break;
+ case AVCOL_TRC_BT709:
+ case AVCOL_TRC_SMPTE170M:
+ mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_TRANSFER,
+ CJNIMediaFormat::COLOR_TRANSFER_SDR_VIDEO);
+ break;
+ case AVCOL_TRC_SMPTE2084:
+ mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_TRANSFER,
+ CJNIMediaFormat::COLOR_TRANSFER_ST2084);
+ break;
+ case AVCOL_TRC_ARIB_STD_B67:
+ mediaformat.setInteger(CJNIMediaFormat::KEY_COLOR_TRANSFER,
+ CJNIMediaFormat::COLOR_TRANSFER_HLG);
+ break;
+ default:
+ CLog::Log(LOGWARNING,
+ "CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec Unhandled Transfer "
+ "characteristic: {}",
+ m_hints.colorTransferCharacteristic);
+ break;
+ }
- std::vector<uint8_t> hdr_static_data = GetHDRStaticMetadata();
- if (!hdr_static_data.empty())
- {
- CJNIByteBuffer bytebuffer = CJNIByteBuffer::allocateDirect(hdr_static_data.size());
- void* dts_ptr = xbmc_jnienv()->GetDirectBufferAddress(bytebuffer.get_raw());
- memcpy(dts_ptr, hdr_static_data.data(), hdr_static_data.size());
- mediaformat.setByteBuffer(CJNIMediaFormat::KEY_HDR_STATIC_INFO, bytebuffer);
- }
+ std::vector<uint8_t> hdr_static_data = GetHDRStaticMetadata();
+ if (!hdr_static_data.empty())
+ {
+ CJNIByteBuffer bytebuffer = CJNIByteBuffer::allocateDirect(hdr_static_data.size());
+ void* dts_ptr = xbmc_jnienv()->GetDirectBufferAddress(bytebuffer.get_raw());
+ memcpy(dts_ptr, hdr_static_data.data(), hdr_static_data.size());
+ mediaformat.setByteBuffer(CJNIMediaFormat::KEY_HDR_STATIC_INFO, bytebuffer);
}
// handle codec extradata
@@ -1740,14 +1731,10 @@ void CDVDVideoCodecAndroidMediaCodec::ConfigureOutputFormat(CJNIMediaFormat& med
height = mediaformat.getInteger(CJNIMediaFormat::KEY_HEIGHT);
if (mediaformat.containsKey(CJNIMediaFormat::KEY_COLOR_FORMAT))
color_format = mediaformat.getInteger(CJNIMediaFormat::KEY_COLOR_FORMAT);
-
- if (CJNIBase::GetSDKVersion() >= 23)
- {
- if (mediaformat.containsKey(CJNIMediaFormat::KEY_STRIDE))
- stride = mediaformat.getInteger(CJNIMediaFormat::KEY_STRIDE);
- if (mediaformat.containsKey(CJNIMediaFormat::KEY_SLICE_HEIGHT))
- slice_height = mediaformat.getInteger(CJNIMediaFormat::KEY_SLICE_HEIGHT);
- }
+ if (mediaformat.containsKey(CJNIMediaFormat::KEY_STRIDE))
+ stride = mediaformat.getInteger(CJNIMediaFormat::KEY_STRIDE);
+ if (mediaformat.containsKey(CJNIMediaFormat::KEY_SLICE_HEIGHT))
+ slice_height = mediaformat.getInteger(CJNIMediaFormat::KEY_SLICE_HEIGHT);
if (CJNIBase::GetSDKVersion() >= 33)
{
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecStarfish.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecStarfish.cpp
index 7e9988de84..e286ea40e0 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecStarfish.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecStarfish.cpp
@@ -12,17 +12,14 @@
#include "DVDCodecs/DVDFactoryCodec.h"
#include "ServiceBroker.h"
#include "cores/VideoPlayer/Buffers/VideoBuffer.h"
-#include "cores/VideoPlayer/Interface/DemuxCrypto.h"
#include "cores/VideoPlayer/Interface/TimingConstants.h"
#include "cores/VideoPlayer/VideoRenderers/RenderManager.h"
-#include "media/decoderfilter/DecoderFilterManager.h"
#include "messaging/ApplicationMessenger.h"
#include "settings/SettingUtils.h"
#include "settings/Settings.h"
#include "settings/SettingsComponent.h"
#include "settings/lib/Setting.h"
#include "utils/BitstreamConverter.h"
-#include "utils/CPUInfo.h"
#include "utils/JSONVariantWriter.h"
#include "utils/log.h"
#include "windowing/wayland/WinSystemWaylandWebOS.h"
@@ -172,9 +169,6 @@ bool CDVDVideoCodecStarfish::OpenInternal(CDVDStreamInfo& hints, CDVDCodecOption
bool isDvhe = (m_hints.codec_tag == MKTAG('d', 'v', 'h', 'e'));
bool isDvh1 = (m_hints.codec_tag == MKTAG('d', 'v', 'h', '1'));
- bool payloadDoviProfile = m_hints.dovi.dv_profile;
- bool payloadElPresentFlag = m_hints.dovi.el_present_flag;
-
// some files don't have dvhe or dvh1 tag set up but have Dolby Vision side data
if (!isDvhe && !isDvh1 && m_hints.hdrType == StreamHdrType::HDR_TYPE_DOLBYVISION)
{
@@ -185,25 +179,6 @@ bool CDVDVideoCodecStarfish::OpenInternal(CDVDStreamInfo& hints, CDVDCodecOption
isDvhe = true;
}
- // set profile 8 and single layer when converting
- if (!removeDovi && convertDovi && m_hints.dovi.dv_profile == 7)
- {
- payloadDoviProfile = 8;
- payloadElPresentFlag = false;
- }
-
- if (!removeDovi && (isDvhe || isDvh1))
- {
- m_formatname = isDvhe ? "starfish-dvhe" : "starfish-dvh1";
-
- payloadArg["option"]["externalStreamingInfo"]["contents"]["DolbyHdrInfo"]
- ["encryptionType"] = "clear"; //"clear", "bl", "el", "all"
- payloadArg["option"]["externalStreamingInfo"]["contents"]["DolbyHdrInfo"]["profileId"] =
- payloadDoviProfile; // profile 0-9
- payloadArg["option"]["externalStreamingInfo"]["contents"]["DolbyHdrInfo"]["trackType"] =
- payloadElPresentFlag ? "dual" : "single"; // "single" / "dual"
- }
-
// check for hevc-hvcC and convert to h265-annex-b
if (m_hints.extradata && !m_hints.cryptoSession)
{
@@ -222,11 +197,31 @@ bool CDVDVideoCodecStarfish::OpenInternal(CDVDStreamInfo& hints, CDVDCodecOption
m_bitstream->SetRemoveHdr10Plus(true);
// Only set for profile 7, container hint allows to skip parsing unnecessarily
- if (m_hints.dovi.dv_profile == 7)
- m_bitstream->SetConvertDovi(convertDovi);
+ // set profile 8 and single layer when converting
+ if (!removeDovi && convertDovi && m_hints.dovi.dv_profile == 7)
+ {
+ m_hints.dovi.dv_profile = 8;
+ m_hints.dovi.el_present_flag = false;
+ m_bitstream->SetConvertDovi(true);
+ }
}
}
+ if (!removeDovi && (isDvhe || isDvh1))
+ {
+ m_formatname = isDvhe ? "starfish-dvhe" : "starfish-dvh1";
+
+ payloadArg["option"]["externalStreamingInfo"]["contents"]["DolbyHdrInfo"]
+ ["encryptionType"] = "clear"; //"clear", "bl", "el", "all"
+ payloadArg["option"]["externalStreamingInfo"]["contents"]["DolbyHdrInfo"]["profileId"] =
+ m_hints.dovi.dv_profile; // profile 0-9
+ payloadArg["option"]["externalStreamingInfo"]["contents"]["DolbyHdrInfo"]["trackType"] =
+ m_hints.dovi.el_present_flag ? "dual" : "single"; // "single" / "dual"
+ }
+
+ if (removeDovi && (isDvhe || isDvh1))
+ m_hints.hdrType = StreamHdrType::HDR_TYPE_HDR10;
+
break;
}
case AV_CODEC_ID_AV1:
@@ -514,62 +509,79 @@ void CDVDVideoCodecStarfish::SetSpeed(int iSpeed)
void CDVDVideoCodecStarfish::SetHDR()
{
+ if (m_hints.hdrType != StreamHdrType::HDR_TYPE_HDR10 &&
+ m_hints.hdrType != StreamHdrType::HDR_TYPE_HLG)
+ return;
+
+ CVariant hdrData;
+ CVariant sei;
+
+ if (ms_hdrInfoMap.find(m_hints.colorTransferCharacteristic) != ms_hdrInfoMap.cend())
+ hdrData["hdrType"] = ms_hdrInfoMap.at(m_hints.colorTransferCharacteristic).data();
+ else
+ hdrData["hdrType"] = "none";
+
if (m_hints.masteringMetadata)
{
- CVariant hdrData;
-
- if (ms_hdrInfoMap.find(m_hints.colorTransferCharacteristic) != ms_hdrInfoMap.cend())
- hdrData["hdrType"] = ms_hdrInfoMap.at(m_hints.colorTransferCharacteristic).data();
- else
- hdrData["hdrType"] = "none";
-
- CVariant sei;
- // for more information, see CTA+861.3-A standard document
- constexpr double maxChromaticity = 50000;
- constexpr double maxLuminance = 10000;
- sei["displayPrimariesX0"] = static_cast<unsigned short>(
- av_q2d(m_hints.masteringMetadata->display_primaries[0][0]) * maxChromaticity + 0.5);
- sei["displayPrimariesY0"] = static_cast<unsigned short>(
- av_q2d(m_hints.masteringMetadata->display_primaries[0][1]) * maxChromaticity + 0.5);
- sei["displayPrimariesX1"] = static_cast<unsigned short>(
- av_q2d(m_hints.masteringMetadata->display_primaries[1][0]) * maxChromaticity + 0.5);
- sei["displayPrimariesY1"] = static_cast<unsigned short>(
- av_q2d(m_hints.masteringMetadata->display_primaries[1][1]) * maxChromaticity + 0.5);
- sei["displayPrimariesX2"] = static_cast<unsigned short>(
- av_q2d(m_hints.masteringMetadata->display_primaries[2][0]) * maxChromaticity + 0.5);
- sei["displayPrimariesY2"] = static_cast<unsigned short>(
- av_q2d(m_hints.masteringMetadata->display_primaries[2][1]) * maxChromaticity + 0.5);
- sei["whitePointX"] = static_cast<unsigned short>(
- av_q2d(m_hints.masteringMetadata->white_point[0]) * maxChromaticity + 0.5);
- sei["whitePointY"] = static_cast<unsigned short>(
- av_q2d(m_hints.masteringMetadata->white_point[1]) * maxChromaticity + 0.5);
- sei["minDisplayMasteringLuminance"] =
- static_cast<unsigned short>(av_q2d(m_hints.masteringMetadata->min_luminance) + 0.5);
- sei["maxDisplayMasteringLuminance"] = static_cast<unsigned short>(
- av_q2d(m_hints.masteringMetadata->max_luminance) * maxLuminance + 0.5);
- // we can have HDR content that does not provide content light level metadata
- if (m_hints.contentLightMetadata)
+ if (m_hints.masteringMetadata->has_primaries)
{
- sei["maxContentLightLevel"] =
- static_cast<unsigned short>(m_hints.contentLightMetadata->MaxCLL);
- sei["maxPicAverageLightLevel"] =
- static_cast<unsigned short>(m_hints.contentLightMetadata->MaxFALL);
+ // for more information, see CTA+861.3-A standard document
+ constexpr int maxChromaticity = 50000;
+ // expected input is in gbr order
+ sei["displayPrimariesX0"] = static_cast<int>(
+ std::round(av_q2d(m_hints.masteringMetadata->display_primaries[1][0]) * maxChromaticity));
+ sei["displayPrimariesY0"] = static_cast<int>(
+ std::round(av_q2d(m_hints.masteringMetadata->display_primaries[1][1]) * maxChromaticity));
+ sei["displayPrimariesX1"] = static_cast<int>(
+ std::round(av_q2d(m_hints.masteringMetadata->display_primaries[2][0]) * maxChromaticity));
+ sei["displayPrimariesY1"] = static_cast<int>(
+ std::round(av_q2d(m_hints.masteringMetadata->display_primaries[2][1]) * maxChromaticity));
+ sei["displayPrimariesX2"] = static_cast<int>(
+ std::round(av_q2d(m_hints.masteringMetadata->display_primaries[0][0]) * maxChromaticity));
+ sei["displayPrimariesY2"] = static_cast<int>(
+ std::round(av_q2d(m_hints.masteringMetadata->display_primaries[0][1]) * maxChromaticity));
+ sei["whitePointX"] = static_cast<int>(
+ std::round(av_q2d(m_hints.masteringMetadata->white_point[0]) * maxChromaticity));
+ sei["whitePointY"] = static_cast<int>(
+ std::round(av_q2d(m_hints.masteringMetadata->white_point[1]) * maxChromaticity));
}
- hdrData["sei"] = sei;
-
- CVariant vui;
- vui["transferCharacteristics"] = static_cast<int>(m_hints.colorTransferCharacteristic);
- vui["colorPrimaries"] = static_cast<int>(m_hints.colorPrimaries);
- vui["matrixCoeffs"] = static_cast<int>(m_hints.colorSpace);
- vui["videoFullRangeFlag"] = m_hints.colorRange == AVCOL_RANGE_JPEG;
- hdrData["vui"] = vui;
- std::string payload;
- CJSONVariantWriter::Write(hdrData, payload, true);
+ if (m_hints.masteringMetadata->has_luminance)
+ {
+ constexpr int maxLuminance = 10000;
+ sei["minDisplayMasteringLuminance"] = static_cast<int>(
+ std::round(av_q2d(m_hints.masteringMetadata->min_luminance) * maxLuminance));
+ sei["maxDisplayMasteringLuminance"] = static_cast<int>(
+ std::round(av_q2d(m_hints.masteringMetadata->max_luminance) * maxLuminance));
+ }
+ }
- CLog::LogFC(LOGDEBUG, LOGVIDEO, "CDVDVideoCodecStarfish: Setting HDR data payload {}", payload);
- m_starfishMediaAPI->setHdrInfo(payload.c_str());
+ // we can have HDR content that does not provide content light level metadata
+ if (m_hints.contentLightMetadata)
+ {
+ sei["maxContentLightLevel"] = m_hints.contentLightMetadata->MaxCLL;
+ sei["maxPicAverageLightLevel"] = m_hints.contentLightMetadata->MaxFALL;
}
+
+ // Some TVs crash on a hdr info message without SEI information
+ // This data is often not available from ffmpeg from the stream (av_stream_get_side_data)
+ // So return here early and let the TV detect the presence of HDR metadata on its own
+ if (sei.empty())
+ return;
+ hdrData["sei"] = sei;
+
+ CVariant vui;
+ vui["transferCharacteristics"] = static_cast<int>(m_hints.colorTransferCharacteristic);
+ vui["colorPrimaries"] = static_cast<int>(m_hints.colorPrimaries);
+ vui["matrixCoeffs"] = static_cast<int>(m_hints.colorSpace);
+ vui["videoFullRangeFlag"] = m_hints.colorRange == AVCOL_RANGE_JPEG;
+ hdrData["vui"] = vui;
+
+ std::string payload;
+ CJSONVariantWriter::Write(hdrData, payload, true);
+
+ CLog::LogFC(LOGDEBUG, LOGVIDEO, "CDVDVideoCodecStarfish: Setting HDR data payload {}", payload);
+ m_starfishMediaAPI->setHdrInfo(payload.c_str());
}
void CDVDVideoCodecStarfish::UpdateFpsDuration()
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/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
index 5bfa52efe7..b43fe8c622 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
@@ -782,7 +782,9 @@ bool CVideoPlayer::OpenInputStream()
{
// find any available external subtitles
std::vector<std::string> filenames;
- CUtil::ScanForExternalSubtitles(m_item.GetDynPath(), filenames);
+
+ if (!URIUtils::IsUPnP(m_item.GetPath()))
+ CUtil::ScanForExternalSubtitles(m_item.GetDynPath(), filenames);
// load any subtitles from file item
std::string key("subtitle:1");
diff --git a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp
index 0924703702..c42f8f3dd7 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp
@@ -112,7 +112,7 @@ bool CVideoPlayerVideo::OpenStream(CDVDStreamInfo hint)
if (hint.codec == AV_CODEC_ID_NONE ||
hint.codec == AV_CODEC_ID_MPEG1VIDEO ||
hint.codec == AV_CODEC_ID_MPEG2VIDEO ||
- hint.codec == AV_CODEC_ID_H264 ||
+ (hint.codec == AV_CODEC_ID_H264 && (hint.codec_tag == 0 || hint.codec_tag == MKTAG('a','v','c','1') || hint.codec_tag == MKTAG('a','v','c','2'))) ||
hint.codec == AV_CODEC_ID_HEVC ||
hint.codec == AV_CODEC_ID_MPEG4 ||
hint.codec == AV_CODEC_ID_WMV3 ||
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp
index 45e3435b74..a0ed2c1ab4 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp
@@ -718,6 +718,7 @@ void CLinuxRendererGLES::UnInit()
m_bConfigured = false;
CServiceBroker::GetWinSystem()->SetHDR(nullptr);
+ m_passthroughHDR = false;
}
bool CLinuxRendererGLES::CreateTexture(int index)
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/VideoPlayer/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp
index b6722ff1d8..b0473573d8 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp
@@ -304,7 +304,7 @@ void CRenderManager::FrameMove()
lock.unlock();
if (!Configure())
return;
-
+ UpdateLatencyTweak();
firstFrame = true;
FrameWait(50ms);
}
@@ -890,11 +890,14 @@ void CRenderManager::PresentBlend(bool clear, DWORD flags, DWORD alpha)
void CRenderManager::UpdateLatencyTweak()
{
float fps = CServiceBroker::GetWinSystem()->GetGfxContext().GetFPS();
+ const bool isHDREnabled = CServiceBroker::GetWinSystem()->GetOSHDRStatus() == HDR_STATUS::HDR_ON;
+
float refresh = fps;
if (CServiceBroker::GetWinSystem()->GetGfxContext().GetVideoResolution() == RES_WINDOW)
refresh = 0; // No idea about refresh rate when windowed, just get the default latency
m_latencyTweak = static_cast<double>(
- CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->GetLatencyTweak(refresh));
+ CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->GetLatencyTweak(refresh,
+ isHDREnabled));
}
void CRenderManager::UpdateResolution()
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h
index 6604291049..d551ad3d06 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h
@@ -82,7 +82,7 @@ protected:
bool m_hasLightMetadata = false;
AVContentLightMetadata m_lightMetadata;
bool m_toneMapping = false;
- ETONEMAPMETHOD m_toneMappingMethod = VS_TONEMAPMETHOD_REINHARD;
+ ETONEMAPMETHOD m_toneMappingMethod = VS_TONEMAPMETHOD_OFF;
float m_toneMappingParam = 1.0;
bool m_colorConversion{false};
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h
index 44b1a8221a..917f0f35f4 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h
@@ -69,7 +69,7 @@ class BaseYUV2RGBGLSLShader : public CGLSLShaderProgram
bool m_hasLightMetadata{false};
AVContentLightMetadata m_lightMetadata;
bool m_toneMapping{false};
- ETONEMAPMETHOD m_toneMappingMethod{VS_TONEMAPMETHOD_REINHARD};
+ ETONEMAPMETHOD m_toneMappingMethod{VS_TONEMAPMETHOD_OFF};
float m_toneMappingParam{1.0};
bool m_colorConversion{false};
diff --git a/xbmc/cores/VideoSettings.cpp b/xbmc/cores/VideoSettings.cpp
index ec474b3ff9..6764e4c5f1 100644
--- a/xbmc/cores/VideoSettings.cpp
+++ b/xbmc/cores/VideoSettings.cpp
@@ -39,7 +39,7 @@ CVideoSettings::CVideoSettings()
m_StereoMode = 0;
m_StereoInvert = false;
m_VideoStream = -1;
- m_ToneMapMethod = VS_TONEMAPMETHOD_REINHARD;
+ m_ToneMapMethod = VS_TONEMAPMETHOD_OFF;
m_ToneMapParam = 1.0f;
m_Orientation = 0;
m_CenterMixLevel = 0;
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/PlayerCoreFactory.cpp b/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp
index f9472c027e..4518796b30 100644
--- a/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp
+++ b/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp
@@ -25,12 +25,15 @@
#include "utils/StringUtils.h"
#include "utils/XMLUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include <mutex>
#include <sstream>
#define PLAYERCOREFACTORY_XML "playercorefactory.xml"
+using namespace KODI;
+
CPlayerCoreFactory::CPlayerCoreFactory(const CProfileManager& profileManager)
: m_settings(CServiceBroker::GetSettingsComponent()->GetSettings()),
m_profileManager(profileManager)
@@ -141,7 +144,7 @@ void CPlayerCoreFactory::GetPlayers(const CFileItem& item, std::vector<std::stri
// "videodefaultplayer"
if (defaultInputstreamPlayerOverride == ForcedPlayer::VIDEO_DEFAULT ||
(defaultInputstreamPlayerOverride == ForcedPlayer::NONE &&
- (item.IsVideo() || (!item.IsAudio() && !item.IsGame()))))
+ (VIDEO::IsVideo(item) || (!item.IsAudio() && !item.IsGame()))))
{
int idx = GetPlayerIndex("videodefaultplayer");
if (idx > -1)
diff --git a/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp b/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp
index cad7399346..d8441dd0c6 100644
--- a/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp
+++ b/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp
@@ -19,10 +19,13 @@
#include "utils/XBMCTinyXML.h"
#include "utils/XMLUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
#include <algorithm>
+using namespace KODI;
+
CPlayerSelectionRule::CPlayerSelectionRule(TiXmlElement* pRule)
{
Initialize(pRule);
@@ -63,9 +66,11 @@ void CPlayerSelectionRule::Initialize(TiXmlElement* pRule)
m_videoCodec = XMLUtils::GetAttribute(pRule, "videocodec");
m_videoResolution = XMLUtils::GetAttribute(pRule, "videoresolution");
m_videoAspect = XMLUtils::GetAttribute(pRule, "videoaspect");
+ m_hdrType = XMLUtils::GetAttribute(pRule, "hdrtype");
m_bStreamDetails = m_audioCodec.length() > 0 || m_audioChannels.length() > 0 ||
- m_videoCodec.length() > 0 || m_videoResolution.length() > 0 || m_videoAspect.length() > 0;
+ m_videoCodec.length() > 0 || m_videoResolution.length() > 0 ||
+ m_videoAspect.length() > 0 || m_hdrType.length() > 0;
if (m_bStreamDetails && !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MYVIDEOS_EXTRACTFLAGS))
{
@@ -114,7 +119,7 @@ void CPlayerSelectionRule::GetPlayers(const CFileItem& item, std::vector<std::st
return;
if (m_tAudio >= 0 && (m_tAudio > 0) != item.IsAudio())
return;
- if (m_tVideo >= 0 && (m_tVideo > 0) != item.IsVideo())
+ if (m_tVideo >= 0 && (m_tVideo > 0) != VIDEO::IsVideo(item))
return;
if (m_tGame >= 0 && (m_tGame > 0) != item.IsGame())
return;
@@ -123,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;
@@ -166,6 +171,13 @@ void CPlayerSelectionRule::GetPlayers(const CFileItem& item, std::vector<std::st
if (CompileRegExp(m_videoAspect, regExp) &&
!MatchesRegExp(CStreamDetails::VideoAspectToAspectDescription(streamDetails.GetVideoAspect()), regExp))
return;
+
+ std::string hdrType{streamDetails.GetVideoHdrType()};
+ if (hdrType.length() == 0)
+ hdrType = "none";
+
+ if (CompileRegExp(m_hdrType, regExp) && !MatchesRegExp(hdrType, regExp))
+ return;
}
CURL url(item.GetDynPath());
diff --git a/xbmc/cores/playercorefactory/PlayerSelectionRule.h b/xbmc/cores/playercorefactory/PlayerSelectionRule.h
index b818d8cb45..694d5c9fb6 100644
--- a/xbmc/cores/playercorefactory/PlayerSelectionRule.h
+++ b/xbmc/cores/playercorefactory/PlayerSelectionRule.h
@@ -55,6 +55,7 @@ private:
std::string m_videoCodec;
std::string m_videoResolution;
std::string m_videoAspect;
+ std::string m_hdrType;
std::string m_playerName;
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.cpp b/xbmc/favourites/FavouritesService.cpp
index 97f55073c3..b175a6c089 100644
--- a/xbmc/favourites/FavouritesService.cpp
+++ b/xbmc/favourites/FavouritesService.cpp
@@ -21,9 +21,12 @@
#include "utils/URIUtils.h"
#include "utils/XBMCTinyXML2.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include <mutex>
+using namespace KODI;
+
namespace
{
bool IsMediasourceOfFavItemUnlocked(const std::shared_ptr<CFileItem>& item)
@@ -71,7 +74,7 @@ bool IsMediasourceOfFavItemUnlocked(const std::shared_ptr<CFileItem>& item)
if (action == CFavouritesURL::Action::PLAY_MEDIA)
{
- if (itemToCheck.IsVideo())
+ if (VIDEO::IsVideo(itemToCheck))
{
if (!profileManager->GetCurrentProfile().videoLocked())
return g_passwordManager.IsMediaFileUnlocked("video", itemToCheck.GetPath());
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 c22eb71284..65d604c18f 100644
--- a/xbmc/guilib/GUIBaseContainer.cpp
+++ b/xbmc/guilib/GUIBaseContainer.cpp
@@ -9,10 +9,12 @@
#include "GUIBaseContainer.h"
#include "FileItem.h"
+#include "FileItemList.h"
#include "GUIInfoManager.h"
#include "GUIListItemLayout.h"
#include "GUIMessage.h"
#include "ServiceBroker.h"
+#include "guilib/GUIListItem.h"
#include "guilib/guiinfo/GUIInfoLabels.h"
#include "guilib/listproviders/IListProvider.h"
#include "input/actions/Action.h"
@@ -875,10 +877,16 @@ bool CGUIBaseContainer::OnClick(int actionID)
int selected = GetSelectedItem();
if (selected >= 0 && selected < static_cast<int>(m_items.size()))
{
+ // One of the actions could trigger a reload of the GUI which destroys
+ // this CGUIBaseContainer and therefore the m_items[selected] we are
+ // going to process. The shared_ptr ensures that item survives until
+ // it has been processed.
+ std::shared_ptr<CGUIListItem> item = m_items[selected];
+
if (m_clickActions.HasActionsMeetingCondition())
- m_clickActions.ExecuteActions(0, GetParentID(), m_items[selected]);
+ m_clickActions.ExecuteActions(0, GetParentID(), item);
else
- m_listProvider->OnClick(m_items[selected]);
+ m_listProvider->OnClick(item);
}
return true;
}
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 12889c9b1d..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
@@ -16,6 +16,8 @@
#include "gui3d.h"
#include "rendering/MatrixGL.h"
#include "rendering/gl/RenderSystemGL.h"
+#include "settings/AdvancedSettings.h"
+#include "settings/SettingsComponent.h"
#include "utils/GLUtils.h"
#include "utils/log.h"
#include "windowing/GraphicContext.h"
@@ -63,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)
{
@@ -88,6 +101,16 @@ bool CGUIFontTTFGL::FirstBegin()
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_texture->GetWidth(), m_texture->GetHeight(), 0,
pixformat, GL_UNSIGNED_BYTE, 0);
+#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
+ if (CServiceBroker::GetRenderSystem()->IsExtSupported("GL_EXT_texture_filter_anisotropic"))
+ {
+ int32_t aniso =
+ CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_guiAnisotropicFiltering;
+ if (aniso > 1)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
+ }
+#endif
+
VerifyGLState();
m_textureStatus = TEXTURE_UPDATED;
}
@@ -117,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;
@@ -126,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();
@@ -135,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
@@ -199,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);
@@ -233,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 ad18836be3..67cceae441 100644
--- a/xbmc/guilib/GUIFontTTFGLES.cpp
+++ b/xbmc/guilib/GUIFontTTFGLES.cpp
@@ -16,6 +16,8 @@
#include "gui3d.h"
#include "rendering/MatrixGL.h"
#include "rendering/gles/RenderSystemGLES.h"
+#include "settings/AdvancedSettings.h"
+#include "settings/SettingsComponent.h"
#include "utils/GLUtils.h"
#include "utils/log.h"
#include "windowing/GraphicContext.h"
@@ -60,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))
@@ -83,6 +96,16 @@ bool CGUIFontTTFGLES::FirstBegin()
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_texture->GetWidth(), m_texture->GetHeight(), 0,
pixformat, GL_UNSIGNED_BYTE, 0);
+#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
+ if (CServiceBroker::GetRenderSystem()->IsExtSupported("GL_EXT_texture_filter_anisotropic"))
+ {
+ int32_t aniso =
+ CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_guiAnisotropicFiltering;
+ if (aniso > 1)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
+ }
+#endif
+
VerifyGLState();
m_textureStatus = TEXTURE_UPDATED;
}
@@ -112,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;
@@ -122,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();
@@ -131,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
@@ -186,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);
@@ -224,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/GUIIncludes.cpp b/xbmc/guilib/GUIIncludes.cpp
index 55d967346f..da8f3a33c9 100644
--- a/xbmc/guilib/GUIIncludes.cpp
+++ b/xbmc/guilib/GUIIncludes.cpp
@@ -529,7 +529,8 @@ void CGUIIncludes::InsertNested(TiXmlElement *controls, TiXmlElement *include, T
}
child = child->NextSiblingElement();
}
- target->RemoveChild(nested);
+ if (nested != node)
+ target->RemoveChild(nested);
}
}
diff --git a/xbmc/guilib/GUILabelControl.dox b/xbmc/guilib/GUILabelControl.dox
index 8501c93114..44bce19494 100644
--- a/xbmc/guilib/GUILabelControl.dox
+++ b/xbmc/guilib/GUILabelControl.dox
@@ -68,9 +68,7 @@ want to be able to give it more content than will fit on one line, then setting:
<wrapmultiline>true</wrapmultiline>
~~~~~~~~~~~~~
-will cause the text to be cut up (at the spaces in the text) onto multiple lines.
-Note that if a single word is larger than <b>`<width>`</b> then it will not be cut, and
-will still overflow.
+Will cause the text to be cut up onto multiple lines.
--------------------------------------------------------------------------------
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/GUITextLayout.cpp b/xbmc/guilib/GUITextLayout.cpp
index 1a300f4bb2..11c671b110 100644
--- a/xbmc/guilib/GUITextLayout.cpp
+++ b/xbmc/guilib/GUITextLayout.cpp
@@ -14,6 +14,9 @@
#include "GUIFont.h"
#include "utils/CharsetConverter.h"
#include "utils/StringUtils.h"
+#include "utils/log.h"
+
+#include <limits>
CGUIString::CGUIString(iString start, iString end, bool carriageReturn)
{
@@ -262,7 +265,7 @@ void CGUITextLayout::UpdateStyled(const vecText& text,
m_colors = colors;
// if we need to wrap the text, then do so
- if (m_wrap && maxWidth > 0)
+ if (m_wrap)
WrapText(text, maxWidth);
else
LineBreakText(text, m_lines);
@@ -540,75 +543,103 @@ void CGUITextLayout::WrapText(const vecText &text, float maxWidth)
if (!m_font)
return;
- int nMaxLines = (m_maxHeight > 0 && m_font->GetLineHeight() > 0)?(int)ceilf(m_maxHeight / m_font->GetLineHeight()):-1;
-
m_lines.clear();
+ if (maxWidth < 0)
+ {
+ CLog::LogF(LOGWARNING, "Cannot wrap the text due to invalid max width value.");
+ return;
+ }
+
+ if (maxWidth == 0) // Unlimited max width
+ {
+ LineBreakText(text, m_lines);
+ return;
+ }
+
std::vector<CGUIString> lines;
LineBreakText(text, lines);
- for (unsigned int i = 0; i < lines.size(); i++)
+ size_t nMaxLines;
+ if (m_maxHeight > 0 && m_font->GetLineHeight() > 0)
+ nMaxLines = static_cast<size_t>(std::ceil(m_maxHeight / m_font->GetLineHeight()));
+ else
+ nMaxLines = std::numeric_limits<size_t>::max();
+
+ // Split lines that exceed the maximum width,
+ // lines can be split by last space char or if there are no spaces by character
+ // to mimics the line behavior of word processors
+ for (const CGUIString& line : lines)
{
- const CGUIString &line = lines[i];
- vecText::const_iterator lastSpace = line.m_text.begin();
+ if (m_lines.size() >= nMaxLines)
+ return;
+
+ if (line.m_text.empty()) // Blank line
+ {
+ m_lines.emplace_back(line);
+ continue;
+ }
+
vecText::const_iterator pos = line.m_text.begin();
- unsigned int lastSpaceInLine = 0;
+ vecText::const_iterator lastBeginPos = line.m_text.begin();
+ vecText::const_iterator lastSpacePos = line.m_text.end();
vecText curLine;
- while (pos != line.m_text.end())
+
+ while (pos < line.m_text.end())
{
// Get the current letter in the string
- character_t letter = *pos;
- // check for a space
- if (CanWrapAtLetter(letter))
+ const character_t& letter = *pos;
+
+ if (CanWrapAtLetter(letter)) // Check for a space char
+ lastSpacePos = pos;
+
+ curLine.emplace_back(letter);
+
+ const float currWidth = m_font->GetTextWidth(curLine);
+
+ if (currWidth > maxWidth)
{
- float width = m_font->GetTextWidth(curLine);
- if (width > maxWidth)
+ if (lastSpacePos > pos) // No space char where split the line, so split by char
{
- if (lastSpace != line.m_text.begin() && lastSpaceInLine > 0)
- {
- CGUIString string(curLine.begin(), curLine.begin() + lastSpaceInLine, false);
- m_lines.push_back(string);
- // check for exceeding our number of lines
- if (nMaxLines > 0 && m_lines.size() >= (size_t)nMaxLines)
- return;
- // skip over spaces
- pos = lastSpace;
- while (pos != line.m_text.end() && IsSpace(*pos))
- ++pos;
- curLine.clear();
- lastSpaceInLine = 0;
- lastSpace = line.m_text.begin();
- continue;
- }
+ // If the pos is equal to lastBeginPos, maxWidth is not large enough to contain 1 character
+ // Push a line with the single character and move on to the next character.
+ if (pos == lastBeginPos)
+ ++pos;
+
+ CGUIString linePart{lastBeginPos, pos, false};
+ m_lines.emplace_back(linePart);
}
- lastSpace = pos;
- lastSpaceInLine = curLine.size();
+ else
+ {
+ CGUIString linePart{lastBeginPos, lastSpacePos, false};
+ m_lines.emplace_back(linePart);
+
+ pos = lastSpacePos + 1;
+ lastSpacePos = line.m_text.end();
+ }
+
+ curLine.clear();
+ lastBeginPos = pos;
+
+ if (m_lines.size() >= nMaxLines)
+ return;
+
+ continue;
}
- curLine.push_back(letter);
+
++pos;
}
- // now add whatever we have left to the string
- float width = m_font->GetTextWidth(curLine);
- if (width > maxWidth)
+
+ // Add the remaining text part
+ if (!curLine.empty())
{
- // too long - put up to the last space on if we can + remove it from what's left.
- if (lastSpace != line.m_text.begin() && lastSpaceInLine > 0)
- {
- CGUIString string(curLine.begin(), curLine.begin() + lastSpaceInLine, false);
- m_lines.push_back(string);
- // check for exceeding our number of lines
- if (nMaxLines > 0 && m_lines.size() >= (size_t)nMaxLines)
- return;
- curLine.erase(curLine.begin(), curLine.begin() + lastSpaceInLine);
- while (curLine.size() && IsSpace(curLine.at(0)))
- curLine.erase(curLine.begin());
- }
+ CGUIString linePart{curLine.begin(), curLine.end(), false};
+ m_lines.emplace_back(linePart);
}
- CGUIString string(curLine.begin(), curLine.end(), true);
- m_lines.push_back(string);
- // check for exceeding our number of lines
- if (nMaxLines > 0 && m_lines.size() >= (size_t)nMaxLines)
- return;
+
+ // Restore carriage return marker for the end of paragraph
+ if (!m_lines.empty())
+ m_lines.back().m_carriageReturn = line.m_carriageReturn;
}
}
diff --git a/xbmc/guilib/TextureGL.cpp b/xbmc/guilib/TextureGL.cpp
index a2cf428b23..300098dbb1 100644
--- a/xbmc/guilib/TextureGL.cpp
+++ b/xbmc/guilib/TextureGL.cpp
@@ -12,6 +12,7 @@
#include "guilib/TextureManager.h"
#include "rendering/RenderSystem.h"
#include "settings/AdvancedSettings.h"
+#include "settings/SettingsComponent.h"
#include "utils/GLUtils.h"
#include "utils/MemUtils.h"
#include "utils/log.h"
@@ -91,6 +92,16 @@ void CGLTexture::LoadToGPU()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
+ if (CServiceBroker::GetRenderSystem()->IsExtSupported("GL_EXT_texture_filter_anisotropic"))
+ {
+ int32_t aniso =
+ CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_guiAnisotropicFiltering;
+ if (aniso > 1)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
+ }
+#endif
+
unsigned int maxSize = CServiceBroker::GetRenderSystem()->GetMaxTextureSize();
if (m_textureHeight > maxSize)
{
diff --git a/xbmc/guilib/guiinfo/GUIInfoLabels.h b/xbmc/guilib/guiinfo/GUIInfoLabels.h
index 8c17ce2a49..68faf15e98 100644
--- a/xbmc/guilib/guiinfo/GUIInfoLabels.h
+++ b/xbmc/guilib/guiinfo/GUIInfoLabels.h
@@ -72,7 +72,6 @@
#define PLAYER_HAS_RESOLUTIONS 64
#define PLAYER_FRAMEADVANCE 65
#define PLAYER_ICON 66
-#define PLAYER_CUTLIST 67
#define PLAYER_CHAPTERS 68
#define PLAYER_EDITLIST 69
#define PLAYER_CUTS 70
@@ -568,8 +567,6 @@
#define SYSTEM_BUILD_VERSION_CODE 1007
#define SYSTEM_BUILD_VERSION_GIT 1008
-static constexpr unsigned int SYSTEM_LOCALE_TIMEZONECOUNTRY = 1009;
-static constexpr unsigned int SYSTEM_LOCALE_TIMEZONE = 1010;
static constexpr unsigned int SYSTEM_LOCALE_REGION = 1011;
static constexpr unsigned int SYSTEM_LOCALE = 1012;
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/PicturesGUIInfo.cpp b/xbmc/guilib/guiinfo/PicturesGUIInfo.cpp
index e2af0e1792..e5920850fe 100644
--- a/xbmc/guilib/guiinfo/PicturesGUIInfo.cpp
+++ b/xbmc/guilib/guiinfo/PicturesGUIInfo.cpp
@@ -20,11 +20,13 @@
#include "utils/StringUtils.h"
#include "utils/URIUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include <map>
#include <memory>
using namespace KODI::GUILIB::GUIINFO;
+using namespace KODI;
static const std::map<int, int> listitem2slideshow_map =
{
@@ -251,7 +253,7 @@ bool CPicturesGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int conte
case SLIDESHOW_ISVIDEO:
{
CSlideShowDelegator& slideShow = CServiceBroker::GetSlideShowDelegator();
- value = slideShow.GetCurrentSlide() && slideShow.GetCurrentSlide()->IsVideo();
+ value = slideShow.GetCurrentSlide() && VIDEO::IsVideo(*slideShow.GetCurrentSlide());
return true;
}
}
diff --git a/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp b/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp
index 3a8e6729e9..4ec5d88952 100644
--- a/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp
+++ b/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp
@@ -296,7 +296,6 @@ bool CPlayerGUIInfo::GetLabel(std::string& value, const CFileItem *item, int con
case PLAYER_EDITLIST:
case PLAYER_CUTS:
case PLAYER_SCENE_MARKERS:
- case PLAYER_CUTLIST:
case PLAYER_CHAPTERS:
value = GetContentRanges(info.m_info);
return true;
@@ -637,7 +636,6 @@ std::string CPlayerGUIInfo::GetContentRanges(int iInfo) const
switch (iInfo)
{
case PLAYER_EDITLIST:
- case PLAYER_CUTLIST:
ranges = GetEditList(data, duration);
break;
case PLAYER_CUTS:
diff --git a/xbmc/guilib/guiinfo/SystemGUIInfo.cpp b/xbmc/guilib/guiinfo/SystemGUIInfo.cpp
index 9a05031e0e..bfad92a308 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"
@@ -327,20 +328,6 @@ bool CSystemGUIInfo::GetLabel(std::string& value, const CFileItem *item, int con
return true;
}
- case SYSTEM_LOCALE_TIMEZONECOUNTRY:
- {
- value = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(
- CSettings::SETTING_LOCALE_TIMEZONECOUNTRY);
- return true;
- }
-
- case SYSTEM_LOCALE_TIMEZONE:
- {
- value = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(
- CSettings::SETTING_LOCALE_TIMEZONE);
- return true;
- }
-
case SYSTEM_LOCALE_REGION:
{
value = g_langInfo.GetCurrentRegion();
diff --git a/xbmc/guilib/guiinfo/VideoGUIInfo.cpp b/xbmc/guilib/guiinfo/VideoGUIInfo.cpp
index 3c2e32a279..9e440b2539 100644
--- a/xbmc/guilib/guiinfo/VideoGUIInfo.cpp
+++ b/xbmc/guilib/guiinfo/VideoGUIInfo.cpp
@@ -35,6 +35,7 @@
#include "utils/StringUtils.h"
#include "utils/URIUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
#include "video/VideoManagerTypes.h"
#include "video/VideoThumbLoader.h"
@@ -43,6 +44,7 @@
using namespace KODI::GUILIB;
using namespace KODI::GUILIB::GUIINFO;
+using namespace KODI;
CVideoGUIInfo::CVideoGUIInfo()
: m_appPlayer(CServiceBroker::GetAppComponents().GetComponent<CApplicationPlayer>())
@@ -61,7 +63,7 @@ int CVideoGUIInfo::GetPercentPlayed(const CVideoInfoTag* tag) const
bool CVideoGUIInfo::InitCurrentItem(CFileItem *item)
{
- if (item && item->IsVideo())
+ if (item && VIDEO::IsVideo(*item))
{
// special case where .strm is used to start an audio stream
if (item->IsInternetStream() && m_appPlayer->IsPlayingAudio())
@@ -479,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;
@@ -494,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;
@@ -515,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/guilib/listproviders/DirectoryProvider.cpp b/xbmc/guilib/listproviders/DirectoryProvider.cpp
index 71233786bc..16e54b958a 100644
--- a/xbmc/guilib/listproviders/DirectoryProvider.cpp
+++ b/xbmc/guilib/listproviders/DirectoryProvider.cpp
@@ -34,6 +34,7 @@
#include "utils/XMLUtils.h"
#include "utils/guilib/GUIContentUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
#include "video/VideoThumbLoader.h"
#include "video/VideoUtils.h"
@@ -47,6 +48,7 @@
using namespace XFILE;
using namespace KODI::MESSAGING;
+using namespace KODI::VIDEO;
using namespace PVR;
class CDirectoryJob : public CJob
@@ -133,7 +135,7 @@ public:
std::shared_ptr<CThumbLoader> getThumbLoader(const CGUIStaticItemPtr& item)
{
- if (item->IsVideo())
+ if (IsVideo(*item))
{
initThumbLoader<CVideoThumbLoader>(InfoTagType::VIDEO);
return m_thumbloaders[InfoTagType::VIDEO];
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/AnnouncementManager.cpp b/xbmc/interfaces/AnnouncementManager.cpp
index 2718adf0d5..46fd378615 100644
--- a/xbmc/interfaces/AnnouncementManager.cpp
+++ b/xbmc/interfaces/AnnouncementManager.cpp
@@ -18,6 +18,7 @@
#include "utils/Variant.h"
#include "utils/log.h"
#include "video/VideoDatabase.h"
+#include "video/VideoFileItemClassify.h"
#include <memory>
#include <mutex>
@@ -26,6 +27,7 @@
#define LOOKUP_PROPERTY "database-lookup"
using namespace ANNOUNCEMENT;
+using namespace KODI::VIDEO;
const std::string CAnnouncementManager::ANNOUNCEMENT_SENDER = "xbmc";
@@ -296,7 +298,7 @@ void CAnnouncementManager::DoAnnounce(AnnouncementFlag flag,
object["item"]["artist"] = item->GetMusicInfoTag()->GetArtist();
}
}
- else if (item->IsVideo())
+ else if (IsVideo(*item))
{
// video item but has no video info tag.
type = "movie";
diff --git a/xbmc/interfaces/builtins/PlayerBuiltins.cpp b/xbmc/interfaces/builtins/PlayerBuiltins.cpp
index d8ff27f1ca..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"
@@ -38,6 +39,7 @@
#include "utils/URIUtils.h"
#include "utils/log.h"
#include "video/PlayerController.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoUtils.h"
#include "video/guilib/VideoGUIUtils.h"
#include "video/guilib/VideoSelectActionProcessor.h"
@@ -48,6 +50,8 @@
#include "Autorun.h"
#endif
+using namespace KODI::VIDEO;
+
/*! \brief Clear current playlist
* \param params (ignored)
*/
@@ -434,7 +438,7 @@ void GetItemsForPlayList(const std::shared_ptr<CFileItem>& item, CFileItemList&
PLAYLIST::Id GetPlayListId(const CFileItem& item)
{
PLAYLIST::Id playlistId{PLAYLIST::TYPE_NONE};
- if (item.IsVideo())
+ if (IsVideo(item))
playlistId = PLAYLIST::TYPE_VIDEO;
else if (item.IsAudio())
playlistId = PLAYLIST::TYPE_MUSIC;
@@ -538,7 +542,7 @@ int PlayOrQueueMedia(const std::vector<std::string>& params, bool forcePlay)
bool containsVideo = false;
for (const auto& i : items)
{
- const bool isVideo = i->IsVideo();
+ const bool isVideo = IsVideo(*i);
containsMusic |= !isVideo;
containsVideo |= isVideo;
@@ -556,7 +560,7 @@ int PlayOrQueueMedia(const std::vector<std::string>& params, bool forcePlay)
{
for (int i = items.Size() - 1; i >= 0; i--) //remove music entries
{
- if (!items[i]->IsVideo())
+ if (!IsVideo(*items[i]))
items.Remove(i);
}
}
@@ -615,7 +619,7 @@ int PlayOrQueueMedia(const std::vector<std::string>& params, bool forcePlay)
if (forcePlay)
{
- if ((item.IsAudio() || item.IsVideo()) && !item.IsSmartPlayList() && !item.IsPVR())
+ if ((item.IsAudio() || IsVideo(item)) && !item.IsSmartPlayList() && !item.IsPVR())
{
if (!item.HasProperty("playlist_type_hint"))
item.SetProperty("playlist_type_hint", GetPlayListId(item));
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 0b0d13e556..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"
@@ -40,10 +41,12 @@
#include "utils/StringUtils.h"
#include "utils/URIUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include "view/GUIViewState.h"
#include <memory>
+using namespace KODI::VIDEO;
using namespace MUSIC_INFO;
using namespace XFILE;
using namespace std::chrono_literals;
@@ -606,7 +609,7 @@ void CAsyncGetItemsForPlaylist::GetItemsForPlaylist(const std::shared_ptr<CFileI
// python files can be played
m_queuedItems.Add(item);
}
- else if (!item->IsNFO() && (item->IsAudio() || item->IsVideo()))
+ else if (!item->IsNFO() && (item->IsAudio() || IsVideo(*item)))
{
const auto itemCheck = m_queuedItems.Get(item->GetPath());
if (!itemCheck || itemCheck->GetStartOffset() != item->GetStartOffset())
@@ -873,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 9dc4e2dddd..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"
@@ -22,6 +23,7 @@
#include "application/Application.h"
#include "application/ApplicationComponents.h"
#include "application/ApplicationPlayer.h"
+#include "video/VideoFileItemClassify.h"
#ifdef HAS_CDDA_RIPPER
#include "cdrip/CDDARipper.h"
#endif
@@ -73,6 +75,7 @@ using namespace MUSIC_GRABBER;
using namespace MUSIC_INFO;
using namespace KODI::MESSAGING;
using KODI::MESSAGING::HELPERS::DialogResponse;
+using namespace KODI::VIDEO;
using namespace std::chrono_literals;
@@ -297,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))
@@ -305,7 +308,7 @@ void CGUIWindowMusicBase::OnItemInfo(int iItem)
return;
}
- if (item->IsVideo() && item->HasVideoInfoTag() &&
+ if (IsVideo(*item) && item->HasVideoInfoTag() &&
item->GetVideoInfoTag()->m_type == MediaTypeMusicVideo)
{ // Music video on a mixed current playlist or navigation by music > music video > artist > video
CGUIDialogVideoInfo::ShowFor(*item);
@@ -348,7 +351,8 @@ void CGUIWindowMusicBase::RetrieveMusicInfo()
for (int i = 0; i < m_vecItems->Size(); ++i)
{
CFileItemPtr pItem = (*m_vecItems)[i];
- if (pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsPicture() || pItem->IsLyrics() || pItem->IsVideo())
+ if (pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsPicture() || pItem->IsLyrics() ||
+ IsVideo(*pItem))
continue;
CMusicInfoTag& tag = *pItem->GetMusicInfoTag();
@@ -728,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 734e7fd067..f03cab5e27 100644
--- a/xbmc/network/upnp/UPnPInternal.cpp
+++ b/xbmc/network/upnp/UPnPInternal.cpp
@@ -28,6 +28,7 @@
#include "utils/StringUtils.h"
#include "utils/URIUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
#include <algorithm>
@@ -38,6 +39,7 @@
#include <Platinum/Source/Platinum/Platinum.h>
+using namespace KODI;
using namespace MUSIC_INFO;
using namespace XFILE;
@@ -203,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 (item.IsVideo() || 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;
}
@@ -528,7 +530,7 @@ PLT_MediaObject* BuildObject(CFileItem& item,
PopulateObjectFromTag(*tag, *object, &file_path, &resource, quirks, upnp_service);
}
}
- else if (item.IsVideoDb() || item.IsVideo())
+ else if (VIDEO::IsVideoDb(item) || VIDEO::IsVideo(item))
{
object->m_ObjectClass.type = "object.item.videoItem";
@@ -672,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());
@@ -818,7 +820,7 @@ PLT_MediaObject* BuildObject(CFileItem& item,
// look for and add external subtitle if we are processing a video file and
// we are being called by a UPnP player or renderer or the user has chosen
// to look for external subtitles
- if (upnp_server != NULL && item.IsVideo() &&
+ if (upnp_server != nullptr && VIDEO::IsVideo(item) &&
(upnp_service == UPnPPlayer || upnp_service == UPnPRenderer ||
settings->GetBool(CSettings::SETTING_SERVICES_UPNPLOOKFOREXTERNALSUBTITLES)))
{
diff --git a/xbmc/network/upnp/UPnPPlayer.cpp b/xbmc/network/upnp/UPnPPlayer.cpp
index 0080141db6..93ef3a58a9 100644
--- a/xbmc/network/upnp/UPnPPlayer.cpp
+++ b/xbmc/network/upnp/UPnPPlayer.cpp
@@ -24,6 +24,7 @@
#include "utils/StringUtils.h"
#include "utils/TimeUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoThumbLoader.h"
#include <mutex>
@@ -33,6 +34,7 @@
#include <Platinum/Source/Platinum/Platinum.h>
using namespace KODI::MESSAGING;
+using namespace KODI;
using KODI::MESSAGING::HELPERS::DialogResponse;
using namespace std::chrono_literals;
@@ -223,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());
@@ -383,7 +385,7 @@ bool CUPnPPlayer::OpenFile(const CFileItem& file, const CPlayerOptions& options)
m_stopremote = true;
m_started = true;
- if (file.IsVideo())
+ if (VIDEO::IsVideo(file))
{
m_hasVideo = true;
}
@@ -417,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 a2374458b5..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"
@@ -30,12 +31,15 @@
#include "utils/StringUtils.h"
#include "utils/URIUtils.h"
#include "utils/Variant.h"
+#include "video/VideoFileItemClassify.h"
#include <inttypes.h>
#include <mutex>
#include <Platinum/Source/Platinum/Platinum.h>
+using namespace KODI::VIDEO;
+
NPT_SET_LOCAL_LOGGER("xbmc.upnp.renderer")
namespace UPNP
@@ -628,7 +632,7 @@ NPT_Result CUPnPRenderer::OnSetNextAVTransportURI(PLT_ActionReference& action)
{
PLAYLIST::Id playlistId = PLAYLIST::TYPE_MUSIC;
- if (item->IsVideo())
+ if (IsVideo(*item))
playlistId = PLAYLIST::TYPE_VIDEO;
// note: auto-deleted when the message is consumed
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 fa7ec34ade..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"
@@ -40,6 +41,7 @@
#include "utils/Variant.h"
#include "utils/XTimeUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include "view/GUIViewState.h"
#define CONTROL_BTNSORTASC 4
@@ -47,6 +49,7 @@
using namespace XFILE;
using namespace KODI::MESSAGING;
+using namespace KODI::VIDEO;
using namespace std::chrono_literals;
@@ -294,7 +297,7 @@ bool CGUIWindowPictures::GetDirectory(const std::string &strDirectory, CFileItem
bool CGUIWindowPictures::OnPlayMedia(int iItem, const std::string &player)
{
- if (m_vecItems->Get(iItem)->IsVideo())
+ if (IsVideo(*m_vecItems->Get(iItem)))
return CGUIMediaWindow::OnPlayMedia(iItem);
return ShowPicture(iItem, false);
@@ -327,7 +330,7 @@ bool CGUIWindowPictures::ShowPicture(int iItem, bool startSlideShow)
{
if (!pItem->m_bIsFolder &&
!(URIUtils::IsRAR(pItem->GetPath()) || URIUtils::IsZIP(pItem->GetPath())) &&
- (pItem->IsPicture() || (bShowVideos && pItem->IsVideo())))
+ (pItem->IsPicture() || (bShowVideos && IsVideo(*pItem))))
{
slideShow.Add(pItem.get());
}
diff --git a/xbmc/pictures/GUIWindowSlideShow.cpp b/xbmc/pictures/GUIWindowSlideShow.cpp
index b70745342e..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"
@@ -42,11 +43,13 @@
#include "utils/Variant.h"
#include "utils/XTimeUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include <memory>
#include <random>
using namespace KODI;
+using namespace KODI::VIDEO;
using namespace MESSAGING;
using namespace XFILE;
using namespace std::chrono_literals;
@@ -293,7 +296,7 @@ void CGUIWindowSlideShow::Add(const CFileItem *picture)
// item without tag; get mimetype then we can tell whether it's video item
item->FillInMimeType();
- if (!item->IsVideo())
+ if (!IsVideo(*item))
// then it is a picture and force tag generation
item->GetPictureInfoTag();
}
@@ -446,13 +449,13 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
{
CLog::Log(LOGERROR, "Error loading the current image {}: {}", m_iCurrentSlide,
m_slides.at(m_iCurrentSlide)->GetPath());
- if (!m_slides.at(m_iCurrentPic)->IsVideo())
+ if (!IsVideo(*m_slides.at(m_iCurrentPic)))
{
// try next if we are in slideshow
CLog::Log(LOGINFO, "set image {} unplayable", m_slides.at(m_iCurrentSlide)->GetPath());
m_slides.at(m_iCurrentSlide)->SetProperty("unplayable", true);
}
- if (m_bLoadNextPic || (bSlideShow && !m_bPause && !m_slides.at(m_iCurrentPic)->IsVideo()))
+ if (m_bLoadNextPic || (bSlideShow && !m_bPause && !IsVideo(*m_slides.at(m_iCurrentPic))))
{
// change to next item, wait loading.
m_iCurrentSlide = m_iNextSlide;
@@ -467,7 +470,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
CLog::Log(LOGERROR, "Error loading the next image {}: {}", m_iNextSlide,
m_slides.at(m_iNextSlide)->GetPath());
// load next image failed, then skip to load next of next if next is not video.
- if (!m_slides.at(m_iNextSlide)->IsVideo())
+ if (!IsVideo(*m_slides.at(m_iNextSlide)))
{
CLog::Log(LOGINFO, "set image {} unplayable", m_slides.at(m_iNextSlide)->GetPath());
m_slides.at(m_iNextSlide)->SetProperty("unplayable", true);
@@ -502,7 +505,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
std::string picturePath = GetPicturePath(item.get());
if (!picturePath.empty())
{
- if (item->IsVideo())
+ if (IsVideo(*item))
CLog::Log(LOGDEBUG, "Loading the thumb {} for current video {}: {}", picturePath,
m_iCurrentSlide, item->GetPath());
else
@@ -532,9 +535,9 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
m_iLastFailedNextSlide = -1;
CFileItemPtr item = m_slides.at(m_iNextSlide);
std::string picturePath = GetPicturePath(item.get());
- if (!picturePath.empty() && (!item->IsVideo() || !m_bSlideShow || m_bPause))
+ if (!picturePath.empty() && (!IsVideo(*item) || !m_bSlideShow || m_bPause))
{
- if (item->IsVideo())
+ if (IsVideo(*item))
CLog::Log(LOGDEBUG, "Loading the thumb {} for next video {}: {}", picturePath, m_iNextSlide,
item->GetPath());
else
@@ -548,7 +551,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
}
}
- bool bPlayVideo = m_slides.at(m_iCurrentSlide)->IsVideo() && m_iVideoSlide != m_iCurrentSlide;
+ bool bPlayVideo = IsVideo(*m_slides.at(m_iCurrentSlide)) && m_iVideoSlide != m_iCurrentSlide;
if (bPlayVideo)
bSlideShow = false;
@@ -577,7 +580,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
// render the next image
if (m_Image[m_iCurrentPic]->DrawNextImage())
{
- if (m_bSlideShow && !m_bPause && m_slides.at(m_iNextSlide)->IsVideo())
+ if (m_bSlideShow && !m_bPause && IsVideo(*m_slides.at(m_iNextSlide)))
{
// do not show thumb of video when playing slideshow
}
@@ -599,7 +602,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
m_Image[1 - m_iCurrentPic]->SetTransitionTime(0,
m_Image[m_iCurrentPic]->GetTransitionTime(1));
m_Image[1 - m_iCurrentPic]->Pause(!m_bSlideShow || m_bPause ||
- m_slides.at(m_iNextSlide)->IsVideo());
+ IsVideo(*m_slides.at(m_iNextSlide)));
m_Image[1 - m_iCurrentPic]->Process(currentTime, regions);
}
else // next pic isn't loaded. We should hang around if it is in progress
@@ -650,7 +653,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
m_iCurrentSlide = m_iNextSlide;
m_iNextSlide = GetNextSlide();
- bPlayVideo = m_slides.at(m_iCurrentSlide)->IsVideo() && m_iVideoSlide != m_iCurrentSlide;
+ bPlayVideo = IsVideo(*m_slides.at(m_iCurrentSlide)) && m_iVideoSlide != m_iCurrentSlide;
}
AnnouncePlayerPlay(m_slides.at(m_iCurrentSlide));
@@ -666,7 +669,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
CServiceBroker::GetGUI()->GetInfoManager().GetInfoProviders().GetPicturesInfoProvider().SetCurrentSlide(m_slides.at(m_iCurrentSlide).get());
RenderPause();
- if (m_slides.at(m_iCurrentSlide)->IsVideo() && appPlayer && appPlayer->IsRenderingGuiLayer())
+ if (IsVideo(*m_slides.at(m_iCurrentSlide)) && appPlayer && appPlayer->IsRenderingGuiLayer())
{
MarkDirtyRegion();
}
@@ -682,7 +685,7 @@ void CGUIWindowSlideShow::Render()
CGraphicContext& gfxCtx = CServiceBroker::GetWinSystem()->GetGfxContext();
gfxCtx.Clear(0xff000000);
- if (m_slides.at(m_iCurrentSlide)->IsVideo())
+ if (IsVideo(*m_slides.at(m_iCurrentSlide)))
{
gfxCtx.SetViewWindow(0, 0, m_coordsRes.iWidth, m_coordsRes.iHeight);
gfxCtx.SetRenderingResolution(gfxCtx.GetVideoResolution(), false);
@@ -722,7 +725,7 @@ void CGUIWindowSlideShow::Render()
void CGUIWindowSlideShow::RenderEx()
{
- if (m_slides.at(m_iCurrentSlide)->IsVideo())
+ if (IsVideo(*m_slides.at(m_iCurrentSlide)))
{
auto& components = CServiceBroker::GetAppComponents();
const auto appPlayer = components.GetComponent<CApplicationPlayer>();
@@ -883,7 +886,7 @@ bool CGUIWindowSlideShow::OnAction(const CAction &action)
case ACTION_PLAYER_PLAY:
if (m_slides.size() == 0)
break;
- if (m_slides.at(m_iCurrentSlide)->IsVideo())
+ if (IsVideo(*m_slides.at(m_iCurrentSlide)))
{
if (!m_bPlayingVideo)
{
@@ -1169,7 +1172,7 @@ void CGUIWindowSlideShow::Move(float fX, float fY)
bool CGUIWindowSlideShow::PlayVideo()
{
CFileItemPtr item = m_slides.at(m_iCurrentSlide);
- if (!item || !item->IsVideo())
+ if (!item || !IsVideo(*item))
return false;
CLog::Log(LOGDEBUG, "Playing current video slide {}", item->GetPath());
m_bPlayingVideo = true;
@@ -1189,7 +1192,7 @@ bool CGUIWindowSlideShow::PlayVideo()
CSlideShowPic::DISPLAY_EFFECT CGUIWindowSlideShow::GetDisplayEffect(int iSlideNumber) const
{
- if (m_bSlideShow && !m_bPause && !m_slides.at(iSlideNumber)->IsVideo())
+ if (m_bSlideShow && !m_bPause && !IsVideo(*m_slides.at(iSlideNumber)))
return CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_SLIDESHOW_DISPLAYEFFECTS) ? CSlideShowPic::EFFECT_RANDOM : CSlideShowPic::EFFECT_NONE;
else
return CSlideShowPic::EFFECT_NO_TIMEOUT;
@@ -1376,7 +1379,7 @@ void CGUIWindowSlideShow::GetCheckedSize(float width, float height, int &maxWidt
std::string CGUIWindowSlideShow::GetPicturePath(CFileItem *item)
{
- bool isVideo = item->IsVideo();
+ bool isVideo = IsVideo(*item);
std::string picturePath = item->GetDynPath();
if (isVideo)
{
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 81b8cfac92..14a880bcec 100644
--- a/xbmc/pictures/PictureInfoLoader.cpp
+++ b/xbmc/pictures/PictureInfoLoader.cpp
@@ -9,10 +9,14 @@
#include "PictureInfoLoader.h"
#include "FileItem.h"
+#include "FileItemList.h"
#include "PictureInfoTag.h"
#include "ServiceBroker.h"
#include "settings/Settings.h"
#include "settings/SettingsComponent.h"
+#include "video/VideoFileItemClassify.h"
+
+using namespace KODI;
CPictureInfoLoader::CPictureInfoLoader()
{
@@ -50,7 +54,8 @@ bool CPictureInfoLoader::LoadItem(CFileItem* pItem)
bool CPictureInfoLoader::LoadItemCached(CFileItem* pItem)
{
- if (!pItem->IsPicture() || pItem->IsZIP() || pItem->IsRAR() || pItem->IsCBR() || pItem->IsCBZ() || pItem->IsInternetStream() || pItem->IsVideo())
+ if (!pItem->IsPicture() || pItem->IsZIP() || pItem->IsRAR() || pItem->IsCBR() || pItem->IsCBZ() ||
+ pItem->IsInternetStream() || VIDEO::IsVideo(*pItem))
return false;
if (pItem->HasPictureInfoTag())
@@ -73,7 +78,8 @@ bool CPictureInfoLoader::LoadItemLookup(CFileItem* pItem)
if (m_pProgressCallback && !pItem->m_bIsFolder)
m_pProgressCallback->SetProgressAdvance();
- if (!pItem->IsPicture() || pItem->IsZIP() || pItem->IsRAR() || pItem->IsCBR() || pItem->IsCBZ() || pItem->IsInternetStream() || pItem->IsVideo())
+ if (!pItem->IsPicture() || pItem->IsZIP() || pItem->IsRAR() || pItem->IsCBR() || pItem->IsCBZ() ||
+ pItem->IsInternetStream() || VIDEO::IsVideo(*pItem))
return false;
if (pItem->HasPictureInfoTag())
diff --git a/xbmc/pictures/PictureThumbLoader.cpp b/xbmc/pictures/PictureThumbLoader.cpp
index 97114e304e..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"
@@ -23,8 +24,10 @@
#include "utils/FileExtensionProvider.h"
#include "utils/FileUtils.h"
#include "utils/URIUtils.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoThumbLoader.h"
+using namespace KODI::VIDEO;
using namespace XFILE;
CPictureThumbLoader::CPictureThumbLoader() : CThumbLoader()
@@ -78,7 +81,8 @@ bool CPictureThumbLoader::LoadItemCached(CFileItem* pItem)
{ // load the thumb from the image file
thumb = pItem->HasArt("thumb") ? pItem->GetArt("thumb") : CTextureUtils::GetWrappedThumbURL(pItem->GetPath());
}
- else if (pItem->IsVideo() && !pItem->IsZIP() && !pItem->IsRAR() && !pItem->IsCBZ() && !pItem->IsCBR() && !pItem->IsPlayList())
+ else if (IsVideo(*pItem) && !pItem->IsZIP() && !pItem->IsRAR() && !pItem->IsCBZ() &&
+ !pItem->IsCBR() && !pItem->IsPlayList())
{ // video
CVideoThumbLoader loader;
loader.LoadItemCached(pItem);
diff --git a/xbmc/platform/android/activity/XBMCApp.cpp b/xbmc/platform/android/activity/XBMCApp.cpp
index 745d9a6b2c..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"
@@ -55,7 +56,6 @@
#include "platform/android/activity/IInputDeviceCallbacks.h"
#include "platform/android/activity/IInputDeviceEventHandler.h"
-#include "platform/android/network/NetworkAndroid.h"
#include "platform/android/powermanagement/AndroidPowerSyscall.h"
#include <memory>
@@ -118,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)
@@ -214,14 +215,23 @@ void CXBMCApp::Announce(ANNOUNCEMENT::AnnouncementFlag flag,
else if (message == "OnStop")
OnPlayBackStopped();
else if (message == "OnSeek")
+ {
+ m_mediaSessionUpdated = false;
UpdateSessionState();
+ }
else if (message == "OnSpeedChanged")
+ {
+ m_mediaSessionUpdated = false;
UpdateSessionState();
+ }
}
else if (flag & Info)
{
if (message == "OnChanged")
+ {
+ m_mediaSessionUpdated = false;
UpdateSessionMetadata();
+ }
}
}
@@ -677,29 +687,6 @@ bool CXBMCApp::SetBuffersGeometry(int width, int height, int format)
return false;
}
-void CXBMCApp::SetRefreshRateCallback(void* rateVariant)
-{
- CVariant* rateV = static_cast<CVariant*>(rateVariant);
- float rate = rateV->asFloat();
- delete rateV;
-
- CJNIWindow window = getWindow();
- if (window)
- {
- CJNIWindowManagerLayoutParams params = window.getAttributes();
- if (fabs(params.getpreferredRefreshRate() - rate) > 0.001f)
- {
- params.setpreferredRefreshRate(rate);
- if (params.getpreferredRefreshRate() > 0.0f)
- {
- window.setAttributes(params);
- return;
- }
- }
- }
- CXBMCApp::Get().m_displayChangeEvent.Set();
-}
-
void CXBMCApp::SetDisplayModeCallback(void* modeVariant)
{
CVariant* modeV = static_cast<CVariant*>(modeVariant);
@@ -720,30 +707,6 @@ void CXBMCApp::SetDisplayModeCallback(void* modeVariant)
CXBMCApp::Get().m_displayChangeEvent.Set();
}
-void CXBMCApp::SetRefreshRate(float rate)
-{
- if (rate < 1.0f)
- return;
-
- CJNIWindow window = getWindow();
- if (window)
- {
- CJNIWindowManagerLayoutParams params = window.getAttributes();
- if (fabs(params.getpreferredRefreshRate() - rate) <= 0.001f)
- return;
- }
-
- m_refreshRate = rate;
- m_displayChangeEvent.Reset();
-
- if (m_hdmiSource)
- dynamic_cast<CWinSystemAndroid*>(CServiceBroker::GetWinSystem())->InitiateModeChange();
-
- CVariant *variant = new CVariant(rate);
- runNativeOnUiThread(SetRefreshRateCallback, variant);
- m_displayChangeEvent.Wait(5000ms);
-}
-
void CXBMCApp::SetDisplayMode(int mode, float rate)
{
if (mode < 1.0)
@@ -785,7 +748,7 @@ int CXBMCApp::android_printf(const char* format, ...)
int len = vsnprintf(0, 0, format, args_copy);
message.resize(len);
result = vsnprintf(&message[0], len + 1, format, args);
- CLog::Log(LOGDEBUG, message);
+ CLog::Log(LOGDEBUG, "{}", message);
}
else
{
@@ -885,6 +848,7 @@ void CXBMCApp::UpdateSessionState()
float speed = 0.0;
const auto& components = CServiceBroker::GetAppComponents();
const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ uint32_t oldPlayState = m_playback_state;
if (m_playback_state != PLAYBACK_STATE_STOPPED)
{
if (appPlayer->HasVideo())
@@ -908,9 +872,13 @@ void CXBMCApp::UpdateSessionState()
else
state = CJNIPlaybackState::STATE_STOPPED;
- builder.setState(state, pos, speed, CJNISystemClock::elapsedRealtime())
- .setActions(CJNIPlaybackState::PLAYBACK_POSITION_UNKNOWN);
- m_mediaSession->updatePlaybackState(builder.build());
+ if ((oldPlayState != m_playback_state) || !m_mediaSessionUpdated)
+ {
+ builder.setState(state, pos, speed, CJNISystemClock::elapsedRealtime())
+ .setActions(CJNIPlaybackState::PLAYBACK_POSITION_UNKNOWN);
+ m_mediaSession->updatePlaybackState(builder.build());
+ m_mediaSessionUpdated = true;
+ }
}
void CXBMCApp::OnPlayBackStarted()
@@ -928,6 +896,7 @@ void CXBMCApp::OnPlayBackStarted()
m_playback_state |= PLAYBACK_STATE_CANNOT_PAUSE;
m_mediaSession->activate(true);
+ m_mediaSessionUpdated = false;
UpdateSessionState();
CJNIIntent intent(ACTION_XBMC_RESUME, CJNIURI::EMPTY, *this, get_class(CJNIContext::get_raw()));
@@ -944,6 +913,7 @@ void CXBMCApp::OnPlayBackPaused()
CLog::Log(LOGDEBUG, "{}", __PRETTY_FUNCTION__);
m_playback_state &= ~PLAYBACK_STATE_PLAYING;
+ m_mediaSessionUpdated = false;
UpdateSessionState();
RequestVisibleBehind(false);
@@ -957,6 +927,7 @@ void CXBMCApp::OnPlayBackStopped()
m_playback_state = PLAYBACK_STATE_STOPPED;
UpdateSessionState();
m_mediaSession->activate(false);
+ m_mediaSessionUpdated = false;
RequestVisibleBehind(false);
CAndroidKey::SetHandleMediaKeys(true);
@@ -977,7 +948,8 @@ std::vector<int> CXBMCApp::GetInputDeviceIds()
void CXBMCApp::ProcessSlow()
{
- if ((m_playback_state & PLAYBACK_STATE_PLAYING) && m_mediaSession->isActive())
+ if ((m_playback_state & PLAYBACK_STATE_PLAYING) && !m_mediaSessionUpdated &&
+ m_mediaSession->isActive())
UpdateSessionState();
}
@@ -1333,22 +1305,21 @@ void CXBMCApp::onReceive(CJNIIntent intent)
}
else if (action == CJNIAudioManager::ACTION_HDMI_AUDIO_PLUG)
{
- m_supportsHdmiAudioPlug = true;
- const bool hdmiPlugged = (intent.getIntExtra(CJNIAudioManager::EXTRA_AUDIO_PLUG_STATE, 0) != 0);
- android_printf("-- HDMI is plugged in: %s", hdmiPlugged ? "yes" : "no");
+ m_hdmiPlugged = (intent.getIntExtra(CJNIAudioManager::EXTRA_AUDIO_PLUG_STATE, 0) != 0);
+ android_printf("-- HDMI is plugged in: %s", m_hdmiPlugged ? "yes" : "no");
if (g_application.IsInitialized())
{
CWinSystemBase* winSystem = CServiceBroker::GetWinSystem();
if (winSystem && dynamic_cast<CWinSystemAndroid*>(winSystem))
- dynamic_cast<CWinSystemAndroid*>(winSystem)->SetHdmiState(hdmiPlugged);
+ dynamic_cast<CWinSystemAndroid*>(winSystem)->SetHdmiState(m_hdmiPlugged);
}
- if (hdmiPlugged && m_aeReset)
+ if (m_hdmiPlugged && m_aeReset)
{
android_printf("CXBMCApp::onReceive: Reset audio engine");
CServiceBroker::GetActiveAE()->DeviceChange();
m_aeReset = false;
}
- if (hdmiPlugged && m_wakeUp)
+ if (m_hdmiPlugged && m_wakeUp)
{
OnWakeup();
m_wakeUp = false;
@@ -1362,11 +1333,11 @@ void CXBMCApp::onReceive(CJNIIntent intent)
// screen but it is actually sent in response to changes in the overall interactive state of
// the device.
CLog::Log(LOGINFO, "Got device wakeup intent");
- if (m_supportsHdmiAudioPlug)
+ if (m_hdmiPlugged)
+ OnWakeup();
+ else
// wake-up sequence continues in ACTION_HDMI_AUDIO_PLUG intent
m_wakeUp = true;
- else
- OnWakeup();
}
else if (action == CJNIIntent::ACTION_SCREEN_OFF)
{
@@ -1412,18 +1383,6 @@ void CXBMCApp::onReceive(CJNIIntent intent)
else if (keycode == CJNIKeyEvent::KEYCODE_MEDIA_STOP)
CAndroidKey::XBMC_Key(keycode, XBMCK_MEDIA_STOP, 0, 0, up);
}
- else if (action == CJNIConnectivityManager::CONNECTIVITY_ACTION)
- {
- if (g_application.IsInitialized())
- {
- if (CJNIBase::GetSDKVersion() < 24)
- {
- CNetworkBase& net = CServiceBroker::GetNetwork();
- CNetworkAndroid* netdroid = static_cast<CNetworkAndroid*>(&net);
- netdroid->RetrieveInterfaces();
- }
- }
- }
}
void CXBMCApp::OnSleep()
@@ -1494,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/XBMCApp.h b/xbmc/platform/android/activity/XBMCApp.h
index 93644c55b4..2e2d8670a0 100644
--- a/xbmc/platform/android/activity/XBMCApp.h
+++ b/xbmc/platform/android/activity/XBMCApp.h
@@ -179,7 +179,6 @@ public:
static float GetSystemVolume();
static void SetSystemVolume(float percent);
- void SetRefreshRate(float rate);
void SetDisplayMode(int mode, float rate);
int GetDPI() const;
@@ -242,7 +241,6 @@ private:
void run();
void stop();
void SetupEnv();
- static void SetRefreshRateCallback(void* rateVariant);
static void SetDisplayModeCallback(void* modeVariant);
static void KeepScreenOnCallback(void* onVariant);
@@ -257,7 +255,8 @@ private:
bool m_hdmiSource{false};
bool m_wakeUp{false};
bool m_aeReset{false};
- bool m_supportsHdmiAudioPlug{false};
+ bool m_hdmiPlugged{true};
+ bool m_mediaSessionUpdated{false};
IInputDeviceCallbacks* m_inputDeviceCallbacks{nullptr};
IInputDeviceEventHandler* m_inputDeviceEventHandler{nullptr};
bool m_hasReqVisible{false};
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/android/network/NetworkAndroid.cpp b/xbmc/platform/android/network/NetworkAndroid.cpp
index 3ebb3b1782..0db2e99c3b 100644
--- a/xbmc/platform/android/network/NetworkAndroid.cpp
+++ b/xbmc/platform/android/network/NetworkAndroid.cpp
@@ -237,11 +237,8 @@ CNetworkAndroid::CNetworkAndroid() : CNetworkBase(), CJNIXBMCConnectivityManager
{
RetrieveInterfaces();
- if (CJNIBase::GetSDKVersion() >= 24)
- {
- CJNIConnectivityManager connman{CXBMCApp::getSystemService(CJNIContext::CONNECTIVITY_SERVICE)};
- connman.registerDefaultNetworkCallback(this->get_raw());
- }
+ CJNIConnectivityManager connman{CXBMCApp::getSystemService(CJNIContext::CONNECTIVITY_SERVICE)};
+ connman.registerDefaultNetworkCallback(this->get_raw());
}
CNetworkAndroid::~CNetworkAndroid()
@@ -251,11 +248,8 @@ CNetworkAndroid::~CNetworkAndroid()
for (auto intf : m_oldInterfaces)
delete intf;
- if (CJNIBase::GetSDKVersion() >= 24)
- {
- CJNIConnectivityManager connman{CXBMCApp::getSystemService(CJNIContext::CONNECTIVITY_SERVICE)};
- connman.unregisterNetworkCallback(this->get_raw());
- }
+ CJNIConnectivityManager connman{CXBMCApp::getSystemService(CJNIContext::CONNECTIVITY_SERVICE)};
+ connman.unregisterNetworkCallback(this->get_raw());
}
bool CNetworkAndroid::GetHostName(std::string& hostname)
diff --git a/xbmc/platform/android/storage/AndroidStorageProvider.cpp b/xbmc/platform/android/storage/AndroidStorageProvider.cpp
index db9b71f1e4..1993d45e42 100644
--- a/xbmc/platform/android/storage/AndroidStorageProvider.cpp
+++ b/xbmc/platform/android/storage/AndroidStorageProvider.cpp
@@ -145,11 +145,19 @@ void CAndroidStorageProvider::GetLocalDrives(VECSOURCES &localDrives)
void CAndroidStorageProvider::GetRemovableDrives(VECSOURCES& removableDrives)
{
- if (CJNIBase::GetSDKVersion() >= 24)
+ bool inError = false;
+
+ CJNIStorageManager manager(CJNIContext::getSystemService(CJNIContext::STORAGE_SERVICE));
+ if (xbmc_jnienv()->ExceptionCheck())
{
- bool inError = false;
+ xbmc_jnienv()->ExceptionDescribe();
+ xbmc_jnienv()->ExceptionClear();
+ inError = true;
+ }
- CJNIStorageManager manager(CJNIContext::getSystemService(CJNIContext::STORAGE_SERVICE));
+ if (!inError)
+ {
+ CJNIStorageVolumes vols = manager.getStorageVolumes();
if (xbmc_jnienv()->ExceptionCheck())
{
xbmc_jnienv()->ExceptionDescribe();
@@ -159,24 +167,36 @@ void CAndroidStorageProvider::GetRemovableDrives(VECSOURCES& removableDrives)
if (!inError)
{
- CJNIStorageVolumes vols = manager.getStorageVolumes();
- if (xbmc_jnienv()->ExceptionCheck())
- {
- xbmc_jnienv()->ExceptionDescribe();
- xbmc_jnienv()->ExceptionClear();
- inError = true;
- }
+ VECSOURCES droidDrives;
- if (!inError)
+ for (int i = 0; i < vols.size(); ++i)
{
- VECSOURCES droidDrives;
+ CJNIStorageVolume vol = vols.get(i);
+ // CLog::Log(LOGDEBUG, "-- Volume: {}({}) -- {}", vol.getPath(), vol.getUserLabel(), vol.getState());
+
+ bool removable = vol.isRemovable();
+ if (xbmc_jnienv()->ExceptionCheck())
+ {
+ xbmc_jnienv()->ExceptionDescribe();
+ xbmc_jnienv()->ExceptionClear();
+ inError = true;
+ break;
+ }
- for (int i = 0; i < vols.size(); ++i)
+ std::string state = vol.getState();
+ if (xbmc_jnienv()->ExceptionCheck())
{
- CJNIStorageVolume vol = vols.get(i);
- // CLog::Log(LOGDEBUG, "-- Volume: {}({}) -- {}", vol.getPath(), vol.getUserLabel(), vol.getState());
+ xbmc_jnienv()->ExceptionDescribe();
+ xbmc_jnienv()->ExceptionClear();
+ inError = true;
+ break;
+ }
- bool removable = vol.isRemovable();
+ if (removable && state == CJNIEnvironment::MEDIA_MOUNTED)
+ {
+ CMediaSource share;
+
+ share.strPath = vol.getPath();
if (xbmc_jnienv()->ExceptionCheck())
{
xbmc_jnienv()->ExceptionDescribe();
@@ -185,7 +205,7 @@ void CAndroidStorageProvider::GetRemovableDrives(VECSOURCES& removableDrives)
break;
}
- std::string state = vol.getState();
+ share.strName = vol.getUserLabel();
if (xbmc_jnienv()->ExceptionCheck())
{
xbmc_jnienv()->ExceptionDescribe();
@@ -194,43 +214,20 @@ void CAndroidStorageProvider::GetRemovableDrives(VECSOURCES& removableDrives)
break;
}
- if (removable && state == CJNIEnvironment::MEDIA_MOUNTED)
- {
- CMediaSource share;
-
- share.strPath = vol.getPath();
- if (xbmc_jnienv()->ExceptionCheck())
- {
- xbmc_jnienv()->ExceptionDescribe();
- xbmc_jnienv()->ExceptionClear();
- inError = true;
- break;
- }
-
- share.strName = vol.getUserLabel();
- if (xbmc_jnienv()->ExceptionCheck())
- {
- xbmc_jnienv()->ExceptionDescribe();
- xbmc_jnienv()->ExceptionClear();
- inError = true;
- break;
- }
+ StringUtils::Trim(share.strName);
+ if (share.strName.empty() || share.strName == "?" ||
+ StringUtils::EqualsNoCase(share.strName, "null"))
+ share.strName = URIUtils::GetFileName(share.strPath);
- StringUtils::Trim(share.strName);
- if (share.strName.empty() || share.strName == "?" ||
- StringUtils::EqualsNoCase(share.strName, "null"))
- share.strName = URIUtils::GetFileName(share.strPath);
-
- share.m_ignore = true;
- droidDrives.emplace_back(share);
- }
+ share.m_ignore = true;
+ droidDrives.emplace_back(share);
}
+ }
- if (!inError)
- {
- removableDrives.insert(removableDrives.end(), droidDrives.begin(), droidDrives.end());
- return;
- }
+ if (!inError)
+ {
+ removableDrives.insert(removableDrives.end(), droidDrives.begin(), droidDrives.end());
+ return;
}
}
}
diff --git a/xbmc/platform/darwin/osx/MediaKeys.mm b/xbmc/platform/darwin/osx/MediaKeys.mm
index 1b939da0eb..f2280e51b0 100644
--- a/xbmc/platform/darwin/osx/MediaKeys.mm
+++ b/xbmc/platform/darwin/osx/MediaKeys.mm
@@ -17,24 +17,32 @@
#import <AppKit/AppKit.h>
#import <IOKit/hidsystem/ev_keymap.h>
+#import <dispatch/dispatch.h>
namespace
{
CGEventRef MediaKeyCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* refcon)
{
- auto tap = (__bridge CMediaKeyTap*)refcon;
- NSEvent* nsEvent = [NSEvent eventWithCGEvent:event];
- if (nsEvent.type == NSEventTypeSystemDefined && nsEvent.subtype == NX_SUBTYPE_AUX_CONTROL_BUTTONS)
- {
- const int keyCode = (([nsEvent data1] & 0xFFFF0000) >> 16);
- const int keyFlags = ([nsEvent data1] & 0x0000FFFF);
- const int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA;
- if (keyState == 1) // if pressed
+ __block bool keyHandled = false;
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ auto tap = (__bridge CMediaKeyTap*)refcon;
+ NSEvent* nsEvent = [NSEvent eventWithCGEvent:event];
+ if (nsEvent.type == NSEventTypeSystemDefined &&
+ nsEvent.subtype == NX_SUBTYPE_AUX_CONTROL_BUTTONS)
{
- if ([tap HandleMediaKey:keyCode])
- return nullptr;
+ const int keyCode = (([nsEvent data1] & 0xFFFF0000) >> 16);
+ const int keyFlags = ([nsEvent data1] & 0x0000FFFF);
+ const int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA;
+ if (keyState == 1) // if pressed
+ {
+ if ([tap HandleMediaKey:keyCode])
+ keyHandled = true;
+ }
}
- }
+ });
+ if (keyHandled)
+ return nullptr;
+
return event;
}
} // namespace
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/CMakeLists.txt b/xbmc/platform/posix/CMakeLists.txt
index 7907159cf9..aa6c2fca79 100644
--- a/xbmc/platform/posix/CMakeLists.txt
+++ b/xbmc/platform/posix/CMakeLists.txt
@@ -6,7 +6,6 @@ set(SOURCES ConvUtils.cpp
PlatformPosix.cpp
PosixMountProvider.cpp
PosixResourceCounter.cpp
- PosixTimezone.cpp
XHandle.cpp
XTimeUtils.cpp)
@@ -17,7 +16,6 @@ set(HEADERS ConvUtils.h
PlatformPosix.h
PosixMountProvider.h
PosixResourceCounter.h
- PosixTimezone.h
XHandle.h)
core_add_library(platform_posix)
diff --git a/xbmc/platform/posix/PosixTimezone.cpp b/xbmc/platform/posix/PosixTimezone.cpp
deleted file mode 100644
index e76fd722e9..0000000000
--- a/xbmc/platform/posix/PosixTimezone.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * 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.
- */
-
-#include "PosixTimezone.h"
-
-#include "ServiceBroker.h"
-#include "XBDateTime.h"
-#include "settings/Settings.h"
-#include "settings/SettingsComponent.h"
-#include "settings/lib/Setting.h"
-#include "settings/lib/SettingDefinitions.h"
-#include "utils/StringUtils.h"
-#include "utils/SystemInfo.h"
-
-#include <algorithm>
-#include <climits>
-#include <cstdlib>
-#include <ctime>
-
-#include "PlatformDefs.h"
-
-CPosixTimezone::CPosixTimezone()
-{
- char* line = NULL;
- size_t linelen = 0;
- int nameonfourthfield = 0;
- std::string s;
- std::vector<std::string> tokens;
-
- // Load timezones
- FILE* fp = fopen("/usr/share/zoneinfo/zone.tab", "r");
- if (fp)
- {
- std::string countryCode;
- std::string timezoneName;
-
- while (getdelim(&line, &linelen, '\n', fp) > 0)
- {
- tokens.clear();
- s = line;
- StringUtils::Trim(s);
-
- if (s.length() == 0)
- continue;
-
- if (s[0] == '#')
- continue;
-
- StringUtils::Tokenize(s, tokens, " \t");
- if (tokens.size() < 3)
- continue;
-
- countryCode = tokens[0];
- timezoneName = tokens[2];
-
- if (m_timezonesByCountryCode.count(countryCode) == 0)
- {
- std::vector<std::string> timezones;
- timezones.push_back(timezoneName);
- m_timezonesByCountryCode[countryCode] = timezones;
- }
- else
- {
- std::vector<std::string>& timezones = m_timezonesByCountryCode[countryCode];
- timezones.push_back(timezoneName);
- }
-
- m_countriesByTimezoneName[timezoneName] = countryCode;
- }
- fclose(fp);
- }
-
- if (line)
- {
- free(line);
- line = NULL;
- linelen = 0;
- }
-
- // Load countries
- fp = fopen("/usr/share/zoneinfo/iso3166.tab", "r");
- if (!fp)
- {
- fp = fopen("/usr/share/misc/iso3166", "r");
- nameonfourthfield = 1;
- }
- if (fp)
- {
- std::string countryCode;
- std::string countryName;
-
- while (getdelim(&line, &linelen, '\n', fp) > 0)
- {
- s = line;
- StringUtils::Trim(s);
-
- //! @todo STRING_CLEANUP
- if (s.length() == 0)
- continue;
-
- if (s[0] == '#')
- continue;
-
- // Search for the first non space from the 2nd character and on
- int i = 2;
- while (s[i] == ' ' || s[i] == '\t') i++;
-
- if (nameonfourthfield)
- {
- // skip three letter
- while (s[i] != ' ' && s[i] != '\t') i++;
- while (s[i] == ' ' || s[i] == '\t') i++;
- // skip number
- while (s[i] != ' ' && s[i] != '\t') i++;
- while (s[i] == ' ' || s[i] == '\t') i++;
- }
-
- countryCode = s.substr(0, 2);
- countryName = s.substr(i);
-
- m_counties.push_back(countryName);
- m_countryByCode[countryCode] = countryName;
- m_countryByName[countryName] = countryCode;
- }
- sort(m_counties.begin(), m_counties.end(), sortstringbyname());
- fclose(fp);
- }
- free(line);
-}
-
-void CPosixTimezone::OnSettingChanged(const std::shared_ptr<const CSetting>& setting)
-{
- if (setting == NULL)
- return;
-
- const std::string &settingId = setting->GetId();
- if (settingId == CSettings::SETTING_LOCALE_TIMEZONE)
- {
- SetTimezone(std::static_pointer_cast<const CSettingString>(setting)->GetValue());
-
- CDateTime::ResetTimezoneBias();
- }
- else if (settingId == CSettings::SETTING_LOCALE_TIMEZONECOUNTRY)
- {
- // nothing to do here. Changing locale.timezonecountry will trigger an
- // update of locale.timezone and automatically adjust its value
- // and execute OnSettingChanged() for it as well (see above)
- }
-}
-
-void CPosixTimezone::OnSettingsLoaded()
-{
- SetTimezone(CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_LOCALE_TIMEZONE));
- CDateTime::ResetTimezoneBias();
-}
-
-std::vector<std::string> CPosixTimezone::GetCounties()
-{
- return m_counties;
-}
-
-std::vector<std::string> CPosixTimezone::GetTimezonesByCountry(const std::string& country)
-{
- return m_timezonesByCountryCode[m_countryByName[country]];
-}
-
-std::string CPosixTimezone::GetCountryByTimezone(const std::string& timezone)
-{
-#if defined(TARGET_DARWIN)
- return "?";
-#else
- return m_countryByCode[m_countriesByTimezoneName[timezone]];
-#endif
-}
-
-void CPosixTimezone::SetTimezone(const std::string& timezoneName)
-{
-#if !defined(TARGET_DARWIN)
- bool use_timezone = true;
-#else
- bool use_timezone = false;
-#endif
-
- if (use_timezone)
- {
- static char env_var[255];
- snprintf(env_var, sizeof(env_var), "TZ=:%s", timezoneName.c_str());
- putenv(env_var);
- tzset();
- }
-}
-
-std::string CPosixTimezone::GetOSConfiguredTimezone()
-{
- std::string timezoneName;
-
- // try Slackware approach first
- timezoneName = ReadFromLocaltime("/etc/localtime-copied-from");
-
- // RHEL and maybe other distros make /etc/localtime a symlink
- if (timezoneName.empty())
- timezoneName = ReadFromLocaltime("/etc/localtime");
-
- // now try Debian approach
- if (timezoneName.empty())
- timezoneName = ReadFromTimezone("/etc/timezone");
-
- return timezoneName;
-}
-
-std::string CPosixTimezone::ReadFromLocaltime(const std::string_view filename)
-{
- char path[PATH_MAX];
- if(realpath(filename.data(), path) == nullptr)
- return "";
-
- // Read the timezone starting from the second last occurrence of /
- std::string str = path;
- size_t pos = str.rfind('/');
- if (pos == std::string::npos)
- return "";
-
- pos = str.rfind('/', pos - 1);
- if (pos == std::string::npos)
- return "";
-
- return str.substr(pos + 1);
-}
-
-std::string CPosixTimezone::ReadFromTimezone(const std::string_view filename)
-{
- std::string timezoneName;
- std::FILE* file = std::fopen(filename.data(), "r");
-
- if (file != nullptr)
- {
- char tz[255];
- if (std::fgets(tz, sizeof(tz), file) != nullptr)
- {
- timezoneName = tz;
- }
-
- std::fclose(file);
- }
-
- return timezoneName;
-}
-
-void CPosixTimezone::SettingOptionsTimezoneCountriesFiller(
- const std::shared_ptr<const CSetting>& setting,
- std::vector<StringSettingOption>& list,
- std::string& current,
- void* data)
-{
- std::vector<std::string> countries = g_timezone.GetCounties();
- for (unsigned int i = 0; i < countries.size(); i++)
- list.emplace_back(countries[i], countries[i]);
-}
-
-void CPosixTimezone::SettingOptionsTimezonesFiller(const std::shared_ptr<const CSetting>& setting,
- std::vector<StringSettingOption>& list,
- std::string& current,
- void* data)
-{
- current = std::static_pointer_cast<const CSettingString>(setting)->GetValue();
- bool found = false;
- std::vector<std::string> timezones = g_timezone.GetTimezonesByCountry(CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_LOCALE_TIMEZONECOUNTRY));
- for (unsigned int i = 0; i < timezones.size(); i++)
- {
- if (!found && StringUtils::EqualsNoCase(timezones[i], current))
- found = true;
-
- list.emplace_back(timezones[i], timezones[i]);
- }
-
- if (!found && !timezones.empty())
- current = timezones[0];
-}
-
-CPosixTimezone g_timezone;
diff --git a/xbmc/platform/posix/PosixTimezone.h b/xbmc/platform/posix/PosixTimezone.h
deleted file mode 100644
index 26a7f09340..0000000000
--- a/xbmc/platform/posix/PosixTimezone.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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
-
-#include "settings/lib/ISettingCallback.h"
-#include "settings/lib/ISettingsHandler.h"
-
-#include <map>
-#include <string>
-#include <vector>
-
-class CSetting;
-struct StringSettingOption;
-
-class CPosixTimezone : public ISettingCallback, public ISettingsHandler
-{
-public:
- CPosixTimezone();
-
- void OnSettingChanged(const std::shared_ptr<const CSetting>& setting) override;
-
- void OnSettingsLoaded() override;
-
- std::string GetOSConfiguredTimezone();
-
- std::vector<std::string> GetCounties();
- std::vector<std::string> GetTimezonesByCountry(const std::string& country);
- std::string GetCountryByTimezone(const std::string& timezone);
-
- void SetTimezone(const std::string& timezone);
- int m_IsDST = 0;
-
- static void SettingOptionsTimezoneCountriesFiller(const std::shared_ptr<const CSetting>& setting,
- std::vector<StringSettingOption>& list,
- std::string& current,
- void* data);
- static void SettingOptionsTimezonesFiller(const std::shared_ptr<const CSetting>& setting,
- std::vector<StringSettingOption>& list,
- std::string& current,
- void* data);
-
-private:
- std::string ReadFromLocaltime(std::string_view filename);
- std::string ReadFromTimezone(std::string_view filename);
- std::vector<std::string> m_counties;
- std::map<std::string, std::string> m_countryByCode;
- std::map<std::string, std::string> m_countryByName;
-
- std::map<std::string, std::vector<std::string>> m_timezonesByCountryCode;
- std::map<std::string, std::string> m_countriesByTimezoneName;
-};
-
-extern CPosixTimezone g_timezone;
-
diff --git a/xbmc/platform/posix/XTimeUtils.cpp b/xbmc/platform/posix/XTimeUtils.cpp
index e78e5cff48..914bf0e72c 100644
--- a/xbmc/platform/posix/XTimeUtils.cpp
+++ b/xbmc/platform/posix/XTimeUtils.cpp
@@ -8,8 +8,6 @@
#include "utils/XTimeUtils.h"
-#include "PosixTimezone.h"
-
#include <errno.h>
#include <mutex>
#include <time.h>
@@ -63,8 +61,6 @@ void GetLocalTime(SystemTime* systemTime)
systemTime->minute = now.tm_min;
systemTime->second = now.tm_sec;
systemTime->milliseconds = 0;
- // NOTE: localtime_r() is not required to set this, but we Assume that it's set here.
- g_timezone.m_IsDST = now.tm_isdst;
}
int FileTimeToLocalFileTime(const FileTime* fileTime, FileTime* localFileTime)
@@ -101,7 +97,6 @@ int SystemTimeToFileTime(const SystemTime* systemTime, FileTime* fileTime)
sysTime.tm_min = systemTime->minute;
sysTime.tm_sec = systemTime->second;
sysTime.tm_yday = dayoffset[sysTime.tm_mon] + (sysTime.tm_mday - 1);
- sysTime.tm_isdst = g_timezone.m_IsDST;
// If this is a leap year, and we're past the 28th of Feb, increment tm_yday.
if (IsLeapYear(systemTime->year) && (sysTime.tm_yday > 58))
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/PlayListM3U.cpp b/xbmc/playlists/PlayListM3U.cpp
index 8853a31275..cb8a9e9077 100644
--- a/xbmc/playlists/PlayListM3U.cpp
+++ b/xbmc/playlists/PlayListM3U.cpp
@@ -16,10 +16,12 @@
#include "utils/CharsetConverter.h"
#include "utils/URIUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
#include <inttypes.h>
+using namespace KODI;
using namespace PLAYLIST;
using namespace XFILE;
@@ -183,7 +185,8 @@ bool CPlayListM3U::Load(const std::string& strFileName)
if (iEndOffset)
lDuration = static_cast<int>(CUtil::ConvertMilliSecsToSecsIntRounded(iEndOffset - iStartOffset));
}
- if (newItem->IsVideo() && !newItem->HasVideoInfoTag()) // File is a video and needs a VideoInfoTag
+ if (VIDEO::IsVideo(*newItem) &&
+ !newItem->HasVideoInfoTag()) // File is a video and needs a VideoInfoTag
newItem->GetVideoInfoTag()->Reset(); // Force VideoInfoTag creation
if (lDuration && newItem->IsAudio())
newItem->GetMusicInfoTag()->SetDuration(lDuration);
diff --git a/xbmc/playlists/PlayListPLS.cpp b/xbmc/playlists/PlayListPLS.cpp
index 369804dba2..d06d5d0ead 100644
--- a/xbmc/playlists/PlayListPLS.cpp
+++ b/xbmc/playlists/PlayListPLS.cpp
@@ -19,6 +19,7 @@
#include "utils/XBMCTinyXML.h"
#include "utils/XMLUtils.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
#include <iostream>
@@ -26,6 +27,7 @@
#include <string>
#include <vector>
+using namespace KODI;
using namespace XFILE;
using namespace PLAYLIST;
@@ -272,7 +274,8 @@ bool CPlayListASX::LoadAsxIniInfo(std::istream &stream)
CLog::Log(LOGINFO, "Adding element {}={}", name, value);
CFileItemPtr newItem(new CFileItem(value));
newItem->SetPath(value);
- if (newItem->IsVideo() && !newItem->HasVideoInfoTag()) // File is a video and needs a VideoInfoTag
+ if (VIDEO::IsVideo(*newItem) &&
+ !newItem->HasVideoInfoTag()) // File is a video and needs a VideoInfoTag
newItem->GetVideoInfoTag()->Reset(); // Force VideoInfoTag creation
Add(newItem);
}
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/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
index b59ba893bd..a9f0f41cc5 100644
--- a/xbmc/settings/AdvancedSettings.cpp
+++ b/xbmc/settings/AdvancedSettings.cpp
@@ -170,6 +170,7 @@ void CAdvancedSettings::Initialize()
m_videoPreferStereoStream = false;
m_videoDefaultLatency = 0.0;
+ m_videoDefaultHdrExtraLatency = 0.0;
m_musicUseTimeSeeking = true;
m_musicTimeSeekForward = 10;
@@ -743,7 +744,7 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file)
TiXmlElement* pVideoLatency = pElement->FirstChildElement("latency");
if (pVideoLatency)
{
- float refresh, refreshmin, refreshmax, delay;
+ float refresh, refreshmin, refreshmax;
TiXmlElement* pRefreshVideoLatency = pVideoLatency->FirstChildElement("refresh");
while (pRefreshVideoLatency)
@@ -761,8 +762,9 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file)
videolatency.refreshmin = refreshmin;
videolatency.refreshmax = refreshmax;
}
- if (XMLUtils::GetFloat(pRefreshVideoLatency, "delay", delay, -600.0f, 600.0f))
- videolatency.delay = delay;
+ XMLUtils::GetFloat(pRefreshVideoLatency, "delay", videolatency.delay, -600.0f, 600.0f);
+ XMLUtils::GetFloat(pRefreshVideoLatency, "hdrextradelay", videolatency.hdrextradelay,
+ -600.0f, 600.0f);
if (videolatency.refreshmin > 0.0f && videolatency.refreshmax >= videolatency.refreshmin)
m_videoRefreshLatency.push_back(videolatency);
@@ -774,8 +776,10 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file)
pRefreshVideoLatency = pRefreshVideoLatency->NextSiblingElement("refresh");
}
- // Get default global display latency
+ // Get default global display latency values
XMLUtils::GetFloat(pVideoLatency, "delay", m_videoDefaultLatency, -600.0f, 600.0f);
+ XMLUtils::GetFloat(pVideoLatency, "hdrextradelay", m_videoDefaultHdrExtraLatency, -600.0f,
+ 600.0f);
}
}
@@ -1219,6 +1223,7 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file)
XMLUtils::GetBoolean(pElement, "visualizedirtyregions", m_guiVisualizeDirtyRegions);
XMLUtils::GetInt(pElement, "algorithmdirtyregions", m_guiAlgorithmDirtyRegions);
XMLUtils::GetBoolean(pElement, "smartredraw", m_guiSmartRedraw);
+ XMLUtils::GetInt(pElement, "anisotropicfiltering", m_guiAnisotropicFiltering);
}
std::string seekSteps;
@@ -1385,16 +1390,26 @@ void CAdvancedSettings::AddSettingsFile(const std::string &filename)
m_settingsFiles.push_back(filename);
}
-float CAdvancedSettings::GetLatencyTweak(float refreshrate)
+float CAdvancedSettings::GetLatencyTweak(float refreshrate, bool isHDREnabled)
{
- float delay = m_videoDefaultLatency;
- for (int i = 0; i < (int) m_videoRefreshLatency.size(); i++)
+ float delay{};
+ const auto& latency =
+ std::find_if(m_videoRefreshLatency.cbegin(), m_videoRefreshLatency.cend(),
+ [refreshrate](const auto& param)
+ { return refreshrate >= param.refreshmin && refreshrate <= param.refreshmax; });
+
+ if (latency != m_videoRefreshLatency.cend()) //refresh rate specific setting is found
{
- RefreshVideoLatency& videolatency = m_videoRefreshLatency[i];
- if (refreshrate >= videolatency.refreshmin && refreshrate <= videolatency.refreshmax)
- delay = videolatency.delay;
+ delay = latency->delay == 0.0f ? m_videoDefaultLatency : latency->delay;
+ if (isHDREnabled)
+ delay +=
+ latency->hdrextradelay == 0.0f ? m_videoDefaultHdrExtraLatency : latency->hdrextradelay;
+ }
+ else //apply default delay settings
+ {
+ delay = isHDREnabled ? m_videoDefaultLatency + m_videoDefaultHdrExtraLatency
+ : m_videoDefaultLatency;
}
-
return delay; // in milliseconds
}
diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
index b5df5118dd..8db9a89a56 100644
--- a/xbmc/settings/AdvancedSettings.h
+++ b/xbmc/settings/AdvancedSettings.h
@@ -94,6 +94,7 @@ struct RefreshVideoLatency
float refreshmax;
float delay;
+ float hdrextradelay;
};
typedef std::vector<TVShowRegexp> SETTINGS_TVSHOWLIST;
@@ -163,6 +164,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
std::vector<RefreshOverride> m_videoAdjustRefreshOverrides;
std::vector<RefreshVideoLatency> m_videoRefreshLatency;
float m_videoDefaultLatency;
+ float m_videoDefaultHdrExtraLatency;
int m_videoCaptureUseOcclusionQuery;
bool m_DXVACheckCompatibility;
bool m_DXVACheckCompatibilityPresent;
@@ -331,6 +333,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
bool m_guiVisualizeDirtyRegions;
int m_guiAlgorithmDirtyRegions;
bool m_guiSmartRedraw;
+ int32_t m_guiAnisotropicFiltering{0};
unsigned int m_addonPackageFolderSize;
bool m_jsonOutputCompact;
@@ -340,7 +343,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
std::vector<std::string> m_settingsFiles;
void ParseSettingsFile(const std::string &file);
- float GetLatencyTweak(float refreshrate);
+ float GetLatencyTweak(float refreshrate, bool isHDREnabled);
bool m_initialized;
void SetDebugMode(bool debug);
diff --git a/xbmc/settings/MediaSettings.cpp b/xbmc/settings/MediaSettings.cpp
index 09aad05861..e3027df998 100644
--- a/xbmc/settings/MediaSettings.cpp
+++ b/xbmc/settings/MediaSettings.cpp
@@ -119,7 +119,7 @@ bool CMediaSettings::Load(const TiXmlNode *settings)
int toneMapMethod;
if (!XMLUtils::GetInt(pElement, "tonemapmethod", toneMapMethod, VS_TONEMAPMETHOD_OFF,
VS_TONEMAPMETHOD_MAX))
- toneMapMethod = VS_TONEMAPMETHOD_REINHARD;
+ toneMapMethod = VS_TONEMAPMETHOD_HABLE;
m_defaultVideoSettings.m_ToneMapMethod = static_cast<ETONEMAPMETHOD>(toneMapMethod);
if (!XMLUtils::GetFloat(pElement, "tonemapparam", m_defaultVideoSettings.m_ToneMapParam, 0.1f, 5.0f))
diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp
index e8e28a59f9..5d940f674c 100644
--- a/xbmc/settings/Settings.cpp
+++ b/xbmc/settings/Settings.cpp
@@ -21,9 +21,6 @@
#include "input/keyboard/KeyboardLayoutManager.h"
#include <mutex>
-#if defined(TARGET_POSIX)
-#include "platform/posix/PosixTimezone.h"
-#endif // defined(TARGET_POSIX)
#include "network/upnp/UPnPSettings.h"
#include "network/WakeOnAccess.h"
#if defined(TARGET_DARWIN_OSX) and defined(HAS_XBMCHELPER)
@@ -327,31 +324,9 @@ void CSettings::InitializeControls()
GetSettingsManager()->RegisterSettingControl("colorbutton", this);
}
-void CSettings::InitializeVisibility()
-{
- // hide some settings if necessary
-#if defined(TARGET_DARWIN_EMBEDDED)
- std::shared_ptr<CSettingString> timezonecountry = std::static_pointer_cast<CSettingString>(GetSettingsManager()->GetSetting(CSettings::SETTING_LOCALE_TIMEZONECOUNTRY));
- std::shared_ptr<CSettingString> timezone = std::static_pointer_cast<CSettingString>(GetSettingsManager()->GetSetting(CSettings::SETTING_LOCALE_TIMEZONE));
-
- timezonecountry->SetRequirementsMet(false);
- timezone->SetRequirementsMet(false);
-#endif
-}
-
void CSettings::InitializeDefaults()
{
// set some default values if necessary
-#if defined(TARGET_POSIX)
- std::shared_ptr<CSettingString> timezonecountry = std::static_pointer_cast<CSettingString>(GetSettingsManager()->GetSetting(CSettings::SETTING_LOCALE_TIMEZONECOUNTRY));
- std::shared_ptr<CSettingString> timezone = std::static_pointer_cast<CSettingString>(GetSettingsManager()->GetSetting(CSettings::SETTING_LOCALE_TIMEZONE));
-
- if (timezonecountry->IsVisible())
- timezonecountry->SetDefault(g_timezone.GetCountryByTimezone(g_timezone.GetOSConfiguredTimezone()));
- if (timezone->IsVisible())
- timezone->SetDefault(g_timezone.GetOSConfiguredTimezone());
-#endif // defined(TARGET_POSIX)
-
#if defined(TARGET_WINDOWS)
// We prefer a fake fullscreen mode (window covering the screen rather than dedicated fullscreen)
// as it works nicer with switching to other applications. However on some systems vsync is broken
@@ -432,10 +407,6 @@ void CSettings::InitializeOptionFillers()
GetSettingsManager()->RegisterSettingOptionsFiller("skincolors", ADDON::CSkinInfo::SettingOptionsSkinColorsFiller);
GetSettingsManager()->RegisterSettingOptionsFiller("skinfonts", ADDON::CSkinInfo::SettingOptionsSkinFontsFiller);
GetSettingsManager()->RegisterSettingOptionsFiller("skinthemes", ADDON::CSkinInfo::SettingOptionsSkinThemesFiller);
-#ifdef TARGET_LINUX
- GetSettingsManager()->RegisterSettingOptionsFiller("timezonecountries", CPosixTimezone::SettingOptionsTimezoneCountriesFiller);
- GetSettingsManager()->RegisterSettingOptionsFiller("timezones", CPosixTimezone::SettingOptionsTimezonesFiller);
-#endif
GetSettingsManager()->RegisterSettingOptionsFiller(
"keyboardlayouts", KEYBOARD::CKeyboardLayoutManager::SettingOptionsKeyboardLayoutsFiller);
GetSettingsManager()->RegisterSettingOptionsFiller(
@@ -532,9 +503,6 @@ void CSettings::InitializeISettingsHandlers()
GetSettingsManager()->RegisterSettingsHandler(&CWakeOnAccess::GetInstance());
GetSettingsManager()->RegisterSettingsHandler(&CRssManager::GetInstance());
GetSettingsManager()->RegisterSettingsHandler(&g_langInfo);
-#if defined(TARGET_LINUX) && !defined(TARGET_ANDROID) && !defined(__UCLIBC__)
- GetSettingsManager()->RegisterSettingsHandler(&g_timezone);
-#endif
GetSettingsManager()->RegisterSettingsHandler(&CMediaSettings::GetInstance());
}
@@ -542,9 +510,6 @@ void CSettings::UninitializeISettingsHandlers()
{
// unregister ISettingsHandler implementations
GetSettingsManager()->UnregisterSettingsHandler(&CMediaSettings::GetInstance());
-#if defined(TARGET_LINUX)
- GetSettingsManager()->UnregisterSettingsHandler(&g_timezone);
-#endif // defined(TARGET_LINUX)
GetSettingsManager()->UnregisterSettingsHandler(&g_langInfo);
GetSettingsManager()->UnregisterSettingsHandler(&CRssManager::GetInstance());
GetSettingsManager()->UnregisterSettingsHandler(&CWakeOnAccess::GetInstance());
@@ -629,13 +594,6 @@ void CSettings::InitializeISettingCallbacks()
settingSet.insert(CSettings::SETTING_LOOKANDFEEL_RSSEDIT);
GetSettingsManager()->RegisterCallback(&CRssManager::GetInstance(), settingSet);
-#if defined(TARGET_LINUX)
- settingSet.clear();
- settingSet.insert(CSettings::SETTING_LOCALE_TIMEZONE);
- settingSet.insert(CSettings::SETTING_LOCALE_TIMEZONECOUNTRY);
- GetSettingsManager()->RegisterCallback(&g_timezone, settingSet);
-#endif
-
#if defined(TARGET_DARWIN_OSX) and defined(HAS_XBMCHELPER)
settingSet.clear();
settingSet.insert(CSettings::SETTING_INPUT_APPLEREMOTEMODE);
@@ -678,9 +636,6 @@ void CSettings::UninitializeISettingCallbacks()
GetSettingsManager()->UnregisterCallback(&g_langInfo);
GetSettingsManager()->UnregisterCallback(&g_passwordManager);
GetSettingsManager()->UnregisterCallback(&CRssManager::GetInstance());
-#if defined(TARGET_LINUX)
- GetSettingsManager()->UnregisterCallback(&g_timezone);
-#endif // defined(TARGET_LINUX)
#if defined(TARGET_DARWIN_OSX) and defined(HAS_XBMCHELPER)
GetSettingsManager()->UnregisterCallback(&XBMCHelper::GetInstance());
#endif
diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h
index bfc5e6072c..35ea531b14 100644
--- a/xbmc/settings/Settings.h
+++ b/xbmc/settings/Settings.h
@@ -45,8 +45,6 @@ public:
static constexpr auto SETTING_LOCALE_CHARSET = "locale.charset";
static constexpr auto SETTING_LOCALE_KEYBOARDLAYOUTS = "locale.keyboardlayouts";
static constexpr auto SETTING_LOCALE_ACTIVEKEYBOARDLAYOUT = "locale.activekeyboardlayout";
- static constexpr auto SETTING_LOCALE_TIMEZONECOUNTRY = "locale.timezonecountry";
- static constexpr auto SETTING_LOCALE_TIMEZONE = "locale.timezone";
static constexpr auto SETTING_LOCALE_SHORTDATEFORMAT = "locale.shortdateformat";
static constexpr auto SETTING_LOCALE_LONGDATEFORMAT = "locale.longdateformat";
static constexpr auto SETTING_LOCALE_TIMEFORMAT = "locale.timeformat";
@@ -602,7 +600,6 @@ protected:
void UninitializeOptionFillers() override;
void InitializeConditions() override;
void UninitializeConditions() override;
- void InitializeVisibility() override;
void InitializeDefaults() override;
void InitializeISettingsHandlers() override;
void UninitializeISettingsHandlers() override;
diff --git a/xbmc/settings/dialogs/GUIDialogSettingsBase.cpp b/xbmc/settings/dialogs/GUIDialogSettingsBase.cpp
index 50af6f9b59..1d878dbb2d 100644
--- a/xbmc/settings/dialogs/GUIDialogSettingsBase.cpp
+++ b/xbmc/settings/dialogs/GUIDialogSettingsBase.cpp
@@ -466,17 +466,20 @@ void CGUIDialogSettingsBase::FreeControls()
control->ClearAll();
}
m_categories.clear();
- FreeSettingsControls();
-}
-void CGUIDialogSettingsBase::DeleteControls()
-{
+ // If we created our own edit control instead of borrowing it then clean it up
if (m_newOriginalEdit)
{
delete m_pOriginalEdit;
- m_pOriginalEdit = NULL;
+ m_pOriginalEdit = nullptr;
+ m_newOriginalEdit = false;
}
+ FreeSettingsControls();
+}
+
+void CGUIDialogSettingsBase::DeleteControls()
+{
m_resetSetting.reset();
m_dummyCategory.reset();
}
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 b3c00efc18..348b574880 100644
--- a/xbmc/utils/GroupUtils.cpp
+++ b/xbmc/utils/GroupUtils.cpp
@@ -9,15 +9,19 @@
#include "GroupUtils.h"
#include "FileItem.h"
+#include "FileItemList.h"
#include "filesystem/MultiPathDirectory.h"
#include "utils/StringUtils.h"
#include "utils/URIUtils.h"
#include "video/VideoDbUrl.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
#include <map>
#include <set>
+using namespace KODI;
+
using SetMap = std::map<int, std::set<CFileItemPtr> >;
bool GroupUtils::Group(GroupBy groupBy, const std::string &baseDir, const CFileItemList &items, CFileItemList &groupedItems, GroupAttribute groupAttributes /* = GroupAttributeNone */)
@@ -127,7 +131,7 @@ bool GroupUtils::Group(GroupBy groupBy, const std::string &baseDir, const CFileI
//accumulate the path for a multipath construction
CFileItem video(movieInfo->m_basePath, false);
- if (video.IsVideo())
+ if (VIDEO::IsVideo(video))
pathSet.insert(URIUtils::GetParentPath(movieInfo->m_basePath));
else
pathSet.insert(movieInfo->m_basePath);
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 aa23b11508..aeb479a4bb 100644
--- a/xbmc/utils/SaveFileStateJob.cpp
+++ b/xbmc/utils/SaveFileStateJob.cpp
@@ -28,6 +28,9 @@
#include "utils/Variant.h"
#include "video/Bookmark.h"
#include "video/VideoDatabase.h"
+#include "video/VideoFileItemClassify.h"
+
+using namespace KODI::VIDEO;
void CSaveFileState::DoWork(CFileItem& item,
CBookmark& bookmark,
@@ -37,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"))
{
@@ -57,7 +60,7 @@ void CSaveFileState::DoWork(CFileItem& item,
return;
}
#endif
- if (item.IsVideo())
+ if (IsVideo(item))
{
std::string redactPath = CURL::GetRedacted(progressTrackingFile);
CLog::Log(LOGDEBUG, "{} - Saving file state for video item {}", __FUNCTION__, redactPath);
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/CMakeLists.txt b/xbmc/video/CMakeLists.txt
index 8586c30626..d867cdbace 100644
--- a/xbmc/video/CMakeLists.txt
+++ b/xbmc/video/CMakeLists.txt
@@ -7,6 +7,7 @@ set(SOURCES Bookmark.cpp
VideoDatabase.cpp
VideoDbUrl.cpp
VideoEmbeddedImageFileLoader.cpp
+ VideoFileItemClassify.cpp
VideoGeneratedImageFileLoader.cpp
VideoInfoDownloader.cpp
VideoInfoScanner.cpp
@@ -28,6 +29,7 @@ set(HEADERS Bookmark.h
VideoDatabase.h
VideoDbUrl.h
VideoEmbeddedImageFileLoader.h
+ VideoFileItemClassify.h
VideoGeneratedImageFileLoader.h
VideoInfoDownloader.h
VideoInfoScanner.h
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 d175929bb6..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)
@@ -4973,22 +4976,19 @@ bool CVideoDatabase::GetArtForAsset(int assetId,
if (nullptr == m_pDS2)
return false; // using dataset 2 as we're likely called in loops on dataset 1
- const std::string sqlFallback{fallback == ArtFallbackOptions::PARENT
- ? StringUtils::Format("UNION "
- "SELECT idMedia, media_type "
- "FROM videoversion "
- "WHERE idFile = {} ",
- assetId)
- : ""};
-
- const std::string sql{PrepareSQL("SELECT art.media_type, art.type, art.url "
- "FROM art "
- "WHERE (media_id, media_type) "
- "IN ("
- "SELECT %i, '%s'"
- "%s"
- ")",
- assetId, MediaTypeVideoVersion, sqlFallback.c_str())};
+ std::string sql{PrepareSQL("SELECT art.media_type, art.type, art.url "
+ "FROM art "
+ "WHERE media_id = %i AND media_type = '%s' ",
+ assetId, MediaTypeVideoVersion)};
+
+ if (fallback == ArtFallbackOptions::PARENT)
+ sql.append(PrepareSQL("UNION "
+ "SELECT art.media_type, art.type, art.url "
+ "FROM art "
+ " JOIN videoversion as vv "
+ " ON art.media_id = vv.idMedia AND art.media_type = vv.media_type "
+ "WHERE idFile = %i",
+ assetId));
m_pDS2->query(sql);
while (!m_pDS2->eof())
diff --git a/xbmc/video/VideoFileItemClassify.cpp b/xbmc/video/VideoFileItemClassify.cpp
new file mode 100644
index 0000000000..d57306013d
--- /dev/null
+++ b/xbmc/video/VideoFileItemClassify.cpp
@@ -0,0 +1,147 @@
+/*
+ * 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 "video/VideoFileItemClassify.h"
+
+#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 */
+ if (StringUtils::StartsWithNoCase(item.GetMimeType(), "video/"))
+ return true;
+
+ if (item.HasVideoInfoTag())
+ return true;
+
+ if (item.HasGameInfoTag())
+ return false;
+
+ if (item.HasMusicInfoTag())
+ return false;
+
+ if (item.HasPictureInfoTag())
+ return false;
+
+ // TV recordings are videos...
+ if (!item.m_bIsFolder && URIUtils::IsPVRTVRecordingFileOrFolder(item.GetPath()))
+ return true;
+
+ // ... all other PVR items are not.
+ if (item.IsPVR())
+ return false;
+
+ if (URIUtils::IsDVD(item.GetPath()))
+ return true;
+
+ std::string extension;
+ if (StringUtils::StartsWithNoCase(item.GetMimeType(), "application/"))
+ { /* check for some standard types */
+ extension = item.GetMimeType().substr(12);
+ if (StringUtils::EqualsNoCase(extension, "ogg") ||
+ StringUtils::EqualsNoCase(extension, "mp4") || StringUtils::EqualsNoCase(extension, "mxf"))
+ return true;
+ }
+
+ //! @todo If the file is a zip file, ask the game clients if any support this
+ // file before assuming it is video.
+
+ return URIUtils::HasExtension(item.GetPath(),
+ 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
new file mode 100644
index 0000000000..55e5aeded7
--- /dev/null
+++ b/xbmc/video/VideoFileItemClassify.h
@@ -0,0 +1,47 @@
+/*
+ * 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
+
+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 aca4162fd5..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"
@@ -42,6 +43,7 @@
#include "utils/URIUtils.h"
#include "utils/Variant.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoManagerTypes.h"
#include "video/VideoThumbLoader.h"
#include "video/dialogs/GUIDialogVideoManagerExtras.h"
@@ -54,6 +56,7 @@
using namespace XFILE;
using namespace ADDON;
using namespace KODI::MESSAGING;
+using namespace KODI::VIDEO;
using KODI::MESSAGING::HELPERS::DialogResponse;
using KODI::UTILITY::CDigest;
@@ -413,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()))
{
@@ -721,8 +724,8 @@ namespace VIDEO
CScraperUrl* pURL,
CGUIDialogProgress* pDlgProgress)
{
- if (pItem->m_bIsFolder || !pItem->IsVideo() || pItem->IsNFO() ||
- (pItem->IsPlayList() && !URIUtils::HasExtension(pItem->GetPath(), ".strm")))
+ if (pItem->m_bIsFolder || !IsVideo(*pItem) || pItem->IsNFO() ||
+ (pItem->IsPlayList() && !URIUtils::HasExtension(pItem->GetPath(), ".strm")))
return INFO_NOT_NEEDED;
if (ProgressCancelled(pDlgProgress, 198, pItem->GetLabel()))
@@ -826,8 +829,8 @@ namespace VIDEO
CScraperUrl* pURL,
CGUIDialogProgress* pDlgProgress)
{
- if (pItem->m_bIsFolder || !pItem->IsVideo() || pItem->IsNFO() ||
- (pItem->IsPlayList() && !URIUtils::HasExtension(pItem->GetPath(), ".strm")))
+ if (pItem->m_bIsFolder || !IsVideo(*pItem) || pItem->IsNFO() ||
+ (pItem->IsPlayList() && !URIUtils::HasExtension(pItem->GetPath(), ".strm")))
return INFO_NOT_NEEDED;
if (ProgressCancelled(pDlgProgress, 20394, pItem->GetLabel()))
@@ -2204,7 +2207,7 @@ namespace VIDEO
KODI::TIME::FileTime time = pItem->m_dateTime;
digest.Update(&time, sizeof(KODI::TIME::FileTime));
}
- if (pItem->IsVideo() && !pItem->IsPlayList() && !pItem->IsNFO())
+ if (IsVideo(*pItem) && !pItem->IsPlayList() && !pItem->IsNFO())
count++;
}
hash = digest.Finalize();
diff --git a/xbmc/video/VideoItemArtworkHandler.cpp b/xbmc/video/VideoItemArtworkHandler.cpp
index 0401c832b3..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"
@@ -23,11 +24,13 @@
#include "utils/Variant.h"
#include "utils/log.h"
#include "video/VideoDatabase.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoScanner.h"
#include "video/VideoInfoTag.h"
#include "video/VideoThumbLoader.h"
#include "video/tags/VideoTagExtractionHelper.h"
+using namespace KODI::VIDEO;
using namespace VIDEO;
using namespace XFILE;
@@ -118,7 +121,7 @@ void CVideoItemArtworkHandler::AddItemPathToFileBrowserSources(std::vector<CMedi
itemDir = m_item->GetVideoInfoTag()->GetPath();
const CFileItem itemTmp(itemDir, false);
- if (itemTmp.IsVideo())
+ if (IsVideo(itemTmp))
itemDir = URIUtils::GetParentPath(itemDir);
AddItemPathStringToFileBrowserSources(sources, itemDir,
diff --git a/xbmc/video/VideoThumbLoader.cpp b/xbmc/video/VideoThumbLoader.cpp
index 1cb634ac2e..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"
@@ -29,6 +30,7 @@
#include "utils/URIUtils.h"
#include "utils/log.h"
#include "video/VideoDatabase.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
#include "video/VideoManagerTypes.h"
#include "video/guilib/VideoVersionHelper.h"
@@ -37,6 +39,7 @@
#include <cstdlib>
#include <utility>
+using namespace KODI::VIDEO;
using namespace XFILE;
using namespace VIDEO;
@@ -180,8 +183,11 @@ bool CVideoThumbLoader::LoadItemCached(CFileItem* pItem)
if (!pItem->HasVideoInfoTag() || !pItem->GetVideoInfoTag()->HasStreamDetails()) // no stream details
{
- if ((pItem->HasVideoInfoTag() && pItem->GetVideoInfoTag()->m_iFileId >= 0) // file (or maybe folder) is in the database
- || (!pItem->m_bIsFolder && pItem->IsVideo())) // Some other video file for which we haven't yet got any database details
+ if ((pItem->HasVideoInfoTag() &&
+ pItem->GetVideoInfoTag()->m_iFileId >= 0) // file (or maybe folder) is in the database
+ || (!pItem->m_bIsFolder &&
+ IsVideo(
+ *pItem))) // Some other video file for which we haven't yet got any database details
{
if (m_videoDatabase->GetStreamDetails(*pItem))
pItem->SetInvalid();
@@ -286,7 +292,7 @@ bool CVideoThumbLoader::LoadItemLookup(CFileItem* pItem)
}
// We can only extract flags/thumbs for file-like items
- if (!pItem->m_bIsFolder && pItem->IsVideo())
+ if (!pItem->m_bIsFolder && IsVideo(*pItem))
{
const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
if (!pItem->HasArt("thumb"))
@@ -408,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,
@@ -549,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);
@@ -595,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 70a1aa0a25..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"
@@ -17,14 +18,20 @@
#include "settings/Settings.h"
#include "settings/SettingsComponent.h"
#include "settings/lib/Setting.h"
+#include "utils/FileUtils.h"
#include "utils/URIUtils.h"
#include "utils/log.h"
#include "video/VideoDatabase.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
+#include <algorithm>
+#include <array>
#include <cstdint>
#include <vector>
+using namespace KODI::VIDEO;
+
namespace
{
VIDEO_UTILS::ResumeInformation GetFolderItemResumeInformation(const CFileItem& item)
@@ -121,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;
@@ -177,6 +184,27 @@ VIDEO_UTILS::ResumeInformation GetNonFolderItemResumeInformation(const CFileItem
namespace VIDEO_UTILS
{
+std::string GetOpticalMediaPath(const CFileItem& item)
+{
+ auto exists = [&item](const std::string& file)
+ {
+ const std::string path = URIUtils::AddFileToFolder(item.GetPath(), file);
+ return CFileUtils::Exists(path);
+ };
+
+ using namespace std::string_literals;
+ const auto files = std::array{
+ "VIDEO_TS.IFO"s, "VIDEO_TS/VIDEO_TS.IFO"s,
+#ifdef HAVE_LIBBLURAY
+ "index.bdmv"s, "INDEX.BDM"s,
+ "BDMV/index.bdmv"s, "BDMV/INDEX.BDM"s,
+#endif
+ };
+
+ const auto it = std::find_if(files.begin(), files.end(), exists);
+ return it != files.end() ? URIUtils::AddFileToFolder(item.GetPath(), *it) : std::string{};
+}
+
bool IsAutoPlayNextItem(const CFileItem& item)
{
if (!item.HasVideoInfoTag())
diff --git a/xbmc/video/VideoUtils.h b/xbmc/video/VideoUtils.h
index f8903730ae..200f650318 100644
--- a/xbmc/video/VideoUtils.h
+++ b/xbmc/video/VideoUtils.h
@@ -14,6 +14,15 @@ class CFileItem;
namespace VIDEO_UTILS
{
+/*!
+ \brief Check whether an item is an optical media folder or its parent.
+ This will return the non-empty path to the playable entry point of the media
+ one or two levels down (VIDEO_TS.IFO for DVDs or index.bdmv for BDs).
+ The returned path will be empty if folder does not meet this criterion.
+ \return non-empty string if item is optical media folder, empty otherwise.
+ */
+std::string GetOpticalMediaPath(const CFileItem& item);
+
/*! \brief Check whether auto play next item is set for the media type of the given item.
\param item [in] the item to check
\return True if auto play next item is active, false otherwise.
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 10708a2f80..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"
@@ -35,6 +36,7 @@
#include "utils/Variant.h"
#include "utils/log.h"
#include "video/VideoDatabase.h"
+#include "video/VideoFileItemClassify.h"
#include "view/ViewState.h"
#include <algorithm>
@@ -48,6 +50,8 @@
#define CONTROL_THUMBS 11
+using namespace KODI::VIDEO;
+
CGUIDialogVideoBookmarks::CGUIDialogVideoBookmarks()
: CGUIDialog(WINDOW_DIALOG_VIDEO_BOOKMARKS, "VideoOSDBookmarks.xml")
{
@@ -531,7 +535,7 @@ bool CGUIDialogVideoBookmarks::AddEpisodeBookmark()
bool CGUIDialogVideoBookmarks::OnAddBookmark()
{
- if (!g_application.CurrentFileItem().IsVideo())
+ if (!IsVideo(g_application.CurrentFileItem()))
return false;
if (CGUIDialogVideoBookmarks::AddBookmark())
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 d2d503c0fc..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"
@@ -51,9 +52,6 @@ CGUIDialogVideoManager::CGUIDialogVideoManager(int windowId)
m_selectedVideoAsset(std::make_shared<CFileItem>())
{
m_loadType = KEEP_IN_MEMORY;
-
- if (!m_database.Open())
- CLog::LogF(LOGERROR, "Failed to open video database!");
}
bool CGUIDialogVideoManager::OnMessage(CGUIMessage& message)
@@ -115,6 +113,9 @@ bool CGUIDialogVideoManager::OnAction(const CAction& action)
void CGUIDialogVideoManager::OnInitWindow()
{
+ if (!m_database.IsOpen() && !m_database.Open())
+ CLog::LogF(LOGERROR, "Failed to open video database!");
+
CGUIDialog::OnInitWindow();
SET_CONTROL_LABEL(CONTROL_LABEL_TITLE,
@@ -127,6 +128,12 @@ void CGUIDialogVideoManager::OnInitWindow()
UpdateControls();
}
+void CGUIDialogVideoManager::OnDeinitWindow(int nextWindowID)
+{
+ CGUIDialog::OnDeinitWindow(nextWindowID);
+ m_database.Close();
+}
+
void CGUIDialogVideoManager::Clear()
{
m_videoAssetsList->Clear();
@@ -198,6 +205,9 @@ void CGUIDialogVideoManager::UpdateControls()
void CGUIDialogVideoManager::Refresh()
{
+ if (!m_database.IsOpen() && !m_database.Open())
+ CLog::LogF(LOGERROR, "Failed to open video database!");
+
Clear();
const int dbId{m_videoAsset->GetVideoInfoTag()->m_iDbId};
diff --git a/xbmc/video/dialogs/GUIDialogVideoManager.h b/xbmc/video/dialogs/GUIDialogVideoManager.h
index b4b043df0a..a76f724259 100644
--- a/xbmc/video/dialogs/GUIDialogVideoManager.h
+++ b/xbmc/video/dialogs/GUIDialogVideoManager.h
@@ -31,6 +31,7 @@ public:
protected:
void OnInitWindow() override;
+ void OnDeinitWindow(int nextWindowID) override;
bool OnMessage(CGUIMessage& message) override;
bool OnAction(const CAction& action) override;
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 176ec8edce..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"
@@ -35,10 +36,13 @@
#include "utils/URIUtils.h"
#include "utils/log.h"
#include "video/VideoDatabase.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
#include "video/VideoUtils.h"
#include "view/GUIViewState.h"
+using namespace KODI::VIDEO;
+
namespace
{
class CAsyncGetItemsForPlaylist : public IRunnable
@@ -134,7 +138,7 @@ void CAsyncGetItemsForPlaylist::GetItemsForPlaylist(const std::shared_ptr<CFileI
if (item->m_bIsFolder)
{
// check if it's a folder with dvd or bluray files, then just add the relevant file
- const std::string mediapath = item->GetOpticalMediaPath();
+ const std::string mediapath = VIDEO_UTILS::GetOpticalMediaPath(*item);
if (!mediapath.empty())
{
m_queuedItems.Add(std::make_shared<CFileItem>(mediapath, false));
@@ -197,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;
@@ -299,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
@@ -307,7 +311,7 @@ void CAsyncGetItemsForPlaylist::GetItemsForPlaylist(const std::shared_ptr<CFileI
itemCopy->SetStartOffset(item->GetStartOffset());
m_queuedItems.Add(itemCopy);
}
- else if (!item->IsNFO() && item->IsVideo())
+ else if (!item->IsNFO() && IsVideo(*item))
{
m_queuedItems.Add(item);
}
@@ -553,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 =
@@ -571,7 +575,7 @@ bool IsItemPlayable(const CFileItem& item)
{
return true;
}
- else if ((!item.m_bIsFolder && item.IsVideo()) || item.IsDVD() || item.IsCDDA())
+ else if ((!item.m_bIsFolder && IsVideo(item)) || item.IsDVD() || item.IsCDDA())
{
return true;
}
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 035ed2c45c..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
@@ -46,7 +49,7 @@ private:
std::shared_ptr<const CFileItem> ChooseVideo(CGUIDialogSelect& dialog,
int headingId,
int buttonId,
- const CFileItemList& itemsToDisplay,
+ CFileItemList& itemsToDisplay,
const CFileItemList& itemsToSwitchTo);
const std::shared_ptr<const CFileItem> m_item;
@@ -151,15 +154,13 @@ std::shared_ptr<const CFileItem> CVideoChooser::ChooseVideoExtra()
std::shared_ptr<const CFileItem> CVideoChooser::ChooseVideo(CGUIDialogSelect& dialog,
int headingId,
int buttonId,
- const CFileItemList& itemsToDisplay,
+ CFileItemList& itemsToDisplay,
const CFileItemList& itemsToSwitchTo)
{
CVideoThumbLoader thumbLoader;
+ thumbLoader.Load(itemsToDisplay);
for (auto& item : itemsToDisplay)
- {
- thumbLoader.LoadItem(item.get());
item->SetLabel2(item->GetVideoInfoTag()->m_strFileNameAndPath);
- }
dialog.Reset();
@@ -174,6 +175,9 @@ std::shared_ptr<const CFileItem> CVideoChooser::ChooseVideo(CGUIDialogSelect& di
dialog.Open();
+ if (thumbLoader.IsLoading())
+ thumbLoader.StopThread();
+
m_switchType = dialog.IsButtonPressed();
if (dialog.IsConfirmed())
return dialog.GetSelectedFileItem();
@@ -277,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/CMakeLists.txt b/xbmc/video/test/CMakeLists.txt
index e03acfbe4d..1cf8a5d878 100644
--- a/xbmc/video/test/CMakeLists.txt
+++ b/xbmc/video/test/CMakeLists.txt
@@ -1,4 +1,6 @@
set(SOURCES TestStacks.cpp
- TestVideoInfoScanner.cpp)
+ TestVideoFileItemClassify.cpp
+ TestVideoInfoScanner.cpp
+ TestVideoUtils.cpp)
core_add_test_library(video_test)
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
new file mode 100644
index 0000000000..3fae8d23a0
--- /dev/null
+++ b/xbmc/video/test/TestVideoFileItemClassify.cpp
@@ -0,0 +1,219 @@
+/*
+ * 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.
+ */
+
+#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"
+
+#include <array>
+
+#include <gtest/gtest.h>
+
+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,
+ bool res = true,
+ const std::string& mime = "",
+ int tag_type = 0)
+ : item(path, false), result(res)
+ {
+ if (!mime.empty())
+ item.SetMimeType(mime);
+ switch (tag_type)
+ {
+ case 1:
+ item.GetVideoInfoTag()->m_strFileNameAndPath = path;
+ break;
+ case 2:
+ item.GetGameInfoTag()->SetGameClient("some_client");
+ break;
+ case 3:
+ item.GetMusicInfoTag()->SetPlayCount(1);
+ break;
+ case 4:
+ item.GetPictureInfoTag()->SetInfo("foo", "bar");
+ ;
+ break;
+ default:
+ break;
+ }
+ }
+
+ CFileItem item;
+ bool result;
+};
+
+class VideoTest : public testing::WithParamInterface<VideoClassifyTest>, public testing::Test
+{
+};
+
+TEST_P(VideoTest, IsVideo)
+{
+ EXPECT_EQ(VIDEO::IsVideo(GetParam().item), GetParam().result);
+}
+
+const auto video_tests = std::array{
+ VideoClassifyTest{"/home/user/video.avi", true, "video/avi"},
+ VideoClassifyTest{"/home/user/video.avi", true, "", 1},
+ VideoClassifyTest{"/home/user/video.avi", false, "", 2},
+ VideoClassifyTest{"/home/user/video.avi", false, "", 3},
+ VideoClassifyTest{"/home/user/video.avi", false, "", 4},
+ VideoClassifyTest{"pvr://recordings/tv/1", true},
+ VideoClassifyTest{"pvr://123", false},
+ VideoClassifyTest{"dvd://VIDEO_TS/video_ts.ifo", true},
+ VideoClassifyTest{"dvd://1", true},
+ VideoClassifyTest{"/home/user/video.not", true, "application/ogg"},
+ VideoClassifyTest{"/home/user/video.not", true, "application/mp4"},
+ VideoClassifyTest{"/home/user/video.not", true, "application/mxf"},
+};
+
+INSTANTIATE_TEST_SUITE_P(TestVideoFileItemClassify, VideoTest, testing::ValuesIn(video_tests));
+
+TEST(TestVideoFileItemClassify, VideoExtensions)
+{
+ const auto& exts = CServiceBroker::GetFileExtensionProvider().GetVideoExtensions();
+ for (const auto& ext : StringUtils::Split(exts, "|"))
+ {
+ if (!ext.empty())
+ 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/test/TestVideoUtils.cpp b/xbmc/video/test/TestVideoUtils.cpp
new file mode 100644
index 0000000000..5c77d9bd50
--- /dev/null
+++ b/xbmc/video/test/TestVideoUtils.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#include "FileItem.h"
+#include "Util.h"
+#include "filesystem/Directory.h"
+#include "platform/Filesystem.h"
+#include "utils/FileUtils.h"
+#include "utils/URIUtils.h"
+#include "video/VideoUtils.h"
+
+#include <array>
+#include <fstream>
+
+#include <gtest/gtest.h>
+
+namespace fs = KODI::PLATFORM::FILESYSTEM;
+
+using OptDef = std::pair<std::string, bool>;
+
+class OpticalMediaPathTest : public testing::WithParamInterface<OptDef>, public testing::Test
+{
+};
+
+TEST_P(OpticalMediaPathTest, GetOpticalMediaPath)
+{
+ std::error_code ec;
+ const std::string temp_path = fs::create_temp_directory(ec);
+ EXPECT_FALSE(ec);
+ const std::string file_path = URIUtils::AddFileToFolder(temp_path, GetParam().first);
+ EXPECT_TRUE(CUtil::CreateDirectoryEx(URIUtils::GetDirectory(file_path)));
+ {
+ std::ofstream of(file_path);
+ }
+ CFileItem item(temp_path, true);
+ if (GetParam().second)
+ EXPECT_EQ(VIDEO_UTILS::GetOpticalMediaPath(item), file_path);
+ else
+ EXPECT_EQ(VIDEO_UTILS::GetOpticalMediaPath(item), "");
+
+ XFILE::CDirectory::RemoveRecursive(temp_path);
+}
+
+const auto mediapath_tests = std::array{
+ OptDef{"VIDEO_TS.IFO", true}, OptDef{"VIDEO_TS/VIDEO_TS.IFO", true},
+ OptDef{"some.file", false},
+#ifdef HAVE_LIBBLURAY
+ OptDef{"index.bdmv", true}, OptDef{"INDEX.BDM", true},
+ OptDef{"BDMV/index.bdmv", true}, OptDef{"BDMV/INDEX.BDM", true},
+#endif
+};
+
+INSTANTIATE_TEST_SUITE_P(TestVideoUtils, OpticalMediaPathTest, testing::ValuesIn(mediapath_tests));
diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp
index 4b31a1c22f..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"
@@ -53,6 +54,7 @@
#include "utils/log.h"
#include "video/VideoDatabase.h"
#include "video/VideoDbUrl.h"
+#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoScanner.h"
#include "video/VideoLibraryQueue.h"
#include "video/VideoManagerTypes.h"
@@ -73,6 +75,7 @@ using namespace VIDEO::GUILIB;
using namespace ADDON;
using namespace PVR;
using namespace KODI::MESSAGING;
+using namespace KODI::VIDEO;
#define CONTROL_BTNVIEWASICONS 2
#define CONTROL_BTNSORTBY 3
@@ -223,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());
@@ -237,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
@@ -268,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)
@@ -286,7 +289,8 @@ bool CGUIWindowVideoBase::OnItemInfo(const CFileItem& fileItem)
CDirectory::GetDirectory(item.GetPath(), items, fileExts, DIR_FLAG_DEFAULTS);
// Check for cases 1_dir/1_dir/.../file (e.g. by packages where have a extra folder)
- while (items.Size() == 1 && items[0]->m_bIsFolder && items[0]->GetOpticalMediaPath().empty())
+ while (items.Size() == 1 && items[0]->m_bIsFolder &&
+ VIDEO_UTILS::GetOpticalMediaPath(*items[0]).empty())
{
const std::string path = items[0]->GetPath();
items.Clear();
@@ -302,7 +306,7 @@ bool CGUIWindowVideoBase::OnItemInfo(const CFileItem& fileItem)
->m_moviesExcludeFromScanRegExps;
for (const auto& i : items)
{
- if (i->IsVideo() && !i->IsPlayList() &&
+ if (IsVideo(*i) && !i->IsPlayList() &&
!CUtil::ExcludeFileOrFolder(i->GetPath(), excludeFromScan))
{
item.SetPath(i->GetPath());
@@ -424,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;
@@ -440,8 +444,14 @@ 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 (!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()
+ item->SetPath(item->GetVideoInfoTag()->GetPath());
+ }
}
}
@@ -485,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;
@@ -732,7 +742,7 @@ void CGUIWindowVideoBase::LoadVideoInfo(CFileItemList& items,
}
// set the watched overlay
- if (pItem->IsVideo())
+ if (IsVideo(*pItem))
pItem->SetOverlayImage(pItem->HasVideoInfoTag() &&
pItem->GetVideoInfoTag()->GetPlayCount() > 0
? CGUIListItem::ICON_OVERLAY_WATCHED
@@ -793,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() &&
@@ -904,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
@@ -960,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());
@@ -1073,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());
@@ -1209,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)
@@ -1258,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;
@@ -1334,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);
@@ -1360,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);
@@ -1369,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())
{
@@ -1511,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/android/AndroidUtils.cpp b/xbmc/windowing/android/AndroidUtils.cpp
index 6b3cdf8568..1396e581a1 100644
--- a/xbmc/windowing/android/AndroidUtils.cpp
+++ b/xbmc/windowing/android/AndroidUtils.cpp
@@ -20,52 +20,14 @@
#include <androidjni/MediaCodecInfo.h>
#include <androidjni/MediaCodecList.h>
-#include <androidjni/System.h>
-#include <androidjni/SystemProperties.h>
#include <androidjni/View.h>
#include <androidjni/Window.h>
-#include <androidjni/WindowManager.h>
-static bool s_hasModeApi = false;
static std::vector<RESOLUTION_INFO> s_res_displayModes;
static RESOLUTION_INFO s_res_cur_displayMode;
-static float currentRefreshRate()
-{
- if (s_hasModeApi)
- return s_res_cur_displayMode.fRefreshRate;
-
- CJNIWindow window = CXBMCApp::getWindow();
- if (window)
- {
- float preferredRate = window.getAttributes().getpreferredRefreshRate();
- if (preferredRate > 20.0f)
- {
- CLog::Log(LOGINFO, "CAndroidUtils: Preferred refresh rate: {:f}", preferredRate);
- return preferredRate;
- }
- CJNIView view(window.getDecorView());
- if (view)
- {
- CJNIDisplay display(view.getDisplay());
- if (display)
- {
- float reportedRate = display.getRefreshRate();
- if (reportedRate > 20.0f)
- {
- CLog::Log(LOGINFO, "CAndroidUtils: Current display refresh rate: {:f}", reportedRate);
- return reportedRate;
- }
- }
- }
- }
- CLog::Log(LOGDEBUG, "found no refresh rate");
- return 60.0;
-}
-
static void fetchDisplayModes()
{
- s_hasModeApi = false;
s_res_displayModes.clear();
CJNIDisplay display = CXBMCApp::getWindow().getDecorView().getDisplay();
@@ -77,8 +39,6 @@ static void fetchDisplayModes()
{
if (m.getPhysicalWidth() > m.getPhysicalHeight()) // Assume unusable if portrait is returned
{
- s_hasModeApi = true;
-
CLog::Log(LOGDEBUG, "CAndroidUtils: current mode: {}: {}x{}@{:f}", m.getModeId(),
m.getPhysicalWidth(), m.getPhysicalHeight(), m.getRefreshRate());
s_res_cur_displayMode.strId = std::to_string(m.getModeId());
@@ -142,35 +102,15 @@ const std::string CAndroidUtils::SETTING_LIMITGUI = "videoscreen.limitgui";
CAndroidUtils::CAndroidUtils()
{
- std::string displaySize;
m_width = m_height = 0;
- if (CJNIBase::GetSDKVersion() >= 23)
- {
- fetchDisplayModes();
- for (const RESOLUTION_INFO& res : s_res_displayModes)
- {
- if (res.iWidth > m_width || res.iHeight > m_height)
- {
- m_width = res.iWidth;
- m_height = res.iHeight;
- }
- }
- }
-
- if (!m_width || !m_height)
+ fetchDisplayModes();
+ for (const RESOLUTION_INFO& res : s_res_displayModes)
{
- // Property available on some devices
- displaySize = CJNISystemProperties::get("sys.display-size", "");
- if (!displaySize.empty())
+ if (res.iWidth > m_width || res.iHeight > m_height)
{
- std::vector<std::string> aSize = StringUtils::Split(displaySize, "x");
- if (aSize.size() == 2)
- {
- m_width = StringUtils::IsInteger(aSize[0]) ? atoi(aSize[0].c_str()) : 0;
- m_height = StringUtils::IsInteger(aSize[1]) ? atoi(aSize[1].c_str()) : 0;
- }
- CLog::Log(LOGDEBUG, "CAndroidUtils: display-size: {}({}x{})", displaySize, m_width, m_height);
+ m_width = res.iWidth;
+ m_height = res.iHeight;
}
}
@@ -224,24 +164,9 @@ bool CAndroidUtils::GetNativeResolution(RESOLUTION_INFO* res) const
CLog::Log(LOGINFO, "CAndroidUtils: window resolution: {}x{}", m_width, m_height);
}
- if (s_hasModeApi)
- {
- *res = s_res_cur_displayMode;
- res->iWidth = m_width;
- res->iHeight = m_height;
- }
- else
- {
- res->strId = "-1";
- res->fRefreshRate = currentRefreshRate();
- res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
- res->bFullScreen = true;
- res->iWidth = m_width;
- res->iHeight = m_height;
- res->fPixelRatio = 1.0f;
- res->iScreenWidth = res->iWidth;
- res->iScreenHeight = res->iHeight;
- }
+ *res = s_res_cur_displayMode;
+ res->iWidth = m_width;
+ res->iHeight = m_height;
res->iSubtitles = res->iHeight;
res->strMode =
StringUtils::Format("{}x{} @ {:.6f}{} - Full Screen", res->iScreenWidth, res->iScreenHeight,
@@ -256,14 +181,8 @@ bool CAndroidUtils::SetNativeResolution(const RESOLUTION_INFO& res)
CLog::Log(LOGINFO, "CAndroidUtils: SetNativeResolution: {}: {}x{} {}x{}@{:f}", res.strId,
res.iWidth, res.iHeight, res.iScreenWidth, res.iScreenHeight, res.fRefreshRate);
- if (s_hasModeApi)
- {
- CXBMCApp::Get().SetDisplayMode(std::atoi(res.strId.c_str()), res.fRefreshRate);
- s_res_cur_displayMode = res;
- }
- else
- CXBMCApp::Get().SetRefreshRate(res.fRefreshRate);
-
+ CXBMCApp::Get().SetDisplayMode(std::atoi(res.strId.c_str()), res.fRefreshRate);
+ s_res_cur_displayMode = res;
CXBMCApp::Get().SetBuffersGeometry(res.iWidth, res.iHeight, 0);
return true;
@@ -272,69 +191,26 @@ bool CAndroidUtils::SetNativeResolution(const RESOLUTION_INFO& res)
bool CAndroidUtils::ProbeResolutions(std::vector<RESOLUTION_INFO>& resolutions)
{
RESOLUTION_INFO cur_res;
- bool ret = GetNativeResolution(&cur_res);
+ GetNativeResolution(&cur_res);
CLog::Log(LOGDEBUG, "CAndroidUtils: ProbeResolutions: {}x{}", m_width, m_height);
- if (s_hasModeApi)
- {
- for (RESOLUTION_INFO res : s_res_displayModes)
- {
- if (m_width && m_height)
- {
- res.iWidth = std::min(res.iWidth, m_width);
- res.iHeight = std::min(res.iHeight, m_height);
- res.iSubtitles = res.iHeight;
- }
- resolutions.push_back(res);
- }
- return true;
- }
-
- if (ret && cur_res.iWidth > 1 && cur_res.iHeight > 1)
+ for (RESOLUTION_INFO res : s_res_displayModes)
{
- std::vector<float> refreshRates;
- CJNIWindow window = CXBMCApp::getWindow();
- if (window)
- {
- CJNIView view = window.getDecorView();
- if (view)
- {
- CJNIDisplay display = view.getDisplay();
- if (display)
- {
- refreshRates = display.getSupportedRefreshRates();
- }
- }
-
- if (!refreshRates.empty())
- {
- for (unsigned int i = 0; i < refreshRates.size(); i++)
- {
- if (refreshRates[i] < 20.0f)
- continue;
- cur_res.fRefreshRate = refreshRates[i];
- cur_res.strMode = StringUtils::Format(
- "{}x{} @ {:.6f}{} - Full Screen", cur_res.iScreenWidth, cur_res.iScreenHeight,
- cur_res.fRefreshRate, cur_res.dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : "");
- resolutions.push_back(cur_res);
- }
- }
- }
- if (resolutions.empty())
+ if (m_width && m_height)
{
- /* No valid refresh rates available, just provide the current one */
- resolutions.push_back(cur_res);
+ res.iWidth = std::min(res.iWidth, m_width);
+ res.iHeight = std::min(res.iHeight, m_height);
+ res.iSubtitles = res.iHeight;
}
- return true;
+ resolutions.push_back(res);
}
- return false;
+ return true;
}
bool CAndroidUtils::UpdateDisplayModes()
{
- if (CJNIBase::GetSDKVersion() >= 23)
- fetchDisplayModes();
+ fetchDisplayModes();
return true;
}
diff --git a/xbmc/windowing/gbm/WinSystemGbm.cpp b/xbmc/windowing/gbm/WinSystemGbm.cpp
index 6569718b3d..72497a2156 100644
--- a/xbmc/windowing/gbm/WinSystemGbm.cpp
+++ b/xbmc/windowing/gbm/WinSystemGbm.cpp
@@ -401,7 +401,7 @@ bool CWinSystemGbm::SetHDR(const VideoPicture* videoPicture)
m_hdr_blob_id = 0;
}
- return true;
+ return false;
}
KODI::UTILS::Colorimetry colorimetry = DRMPRIME::GetColorimetry(*videoPicture);
@@ -501,7 +501,7 @@ bool CWinSystemGbm::SetHDR(const VideoPicture* videoPicture)
drm->SetActive(true);
}
- return true;
+ return m_hdr_blob_id != 0;
}
bool CWinSystemGbm::IsHDRDisplay()
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/wayland/CMakeLists.txt b/xbmc/windowing/wayland/CMakeLists.txt
index d29b97c685..c406de112f 100644
--- a/xbmc/windowing/wayland/CMakeLists.txt
+++ b/xbmc/windowing/wayland/CMakeLists.txt
@@ -68,10 +68,12 @@ if(TARGET_WEBOS)
PROPERTIES GENERATED TRUE)
list(APPEND SOURCES OSScreenSaverWebOS.cpp
+ SeatWebOS.cpp
ShellSurfaceWebOSShell.cpp
WinSystemWaylandWebOS.cpp
${WAYLAND_EXTRA_PROTOCOL_GENERATED_DIR}/wayland-webos-protocols.cpp)
list(APPEND HEADERS OSScreenSaverWebOS.h
+ SeatWebOS.h
ShellSurfaceWebOSShell.h
WinSystemWaylandWebOS.h
${WAYLAND_EXTRA_PROTOCOL_GENERATED_DIR}/wayland-webos-protocols.hpp)
diff --git a/xbmc/windowing/wayland/Seat.cpp b/xbmc/windowing/wayland/Seat.cpp
index de22f1e218..770c274ed6 100644
--- a/xbmc/windowing/wayland/Seat.cpp
+++ b/xbmc/windowing/wayland/Seat.cpp
@@ -136,10 +136,7 @@ void CSeat::SetCursor(std::uint32_t serial, wayland::surface_t const &surface, s
{
if (m_pointer)
{
- // set_cursor on webOS completely breaks pointer input
-#ifndef TARGET_WEBOS
m_pointer.set_cursor(serial, surface, hotspotX, hotspotY);
-#endif
}
}
@@ -182,6 +179,11 @@ void CSeat::HandleKeyboardCapability()
handler->OnKeyboardModifiers(this, serial, modsDepressed, modsLatched, modsLocked, group);
}
};
+ InstallKeyboardRepeatInfo();
+}
+
+void CSeat::InstallKeyboardRepeatInfo()
+{
m_keyboard.on_repeat_info() = [this](std::int32_t rate, std::int32_t delay)
{
for (auto handler : m_rawKeyboardHandlers)
@@ -191,7 +193,6 @@ void CSeat::HandleKeyboardCapability()
};
}
-
void CSeat::HandlePointerCapability()
{
m_pointer.on_enter() = [this](std::uint32_t serial, const wayland::surface_t& surface,
diff --git a/xbmc/windowing/wayland/Seat.h b/xbmc/windowing/wayland/Seat.h
index 095f18dd89..edaf8e4df4 100644
--- a/xbmc/windowing/wayland/Seat.h
+++ b/xbmc/windowing/wayland/Seat.h
@@ -121,7 +121,7 @@ public:
* \param connection connection for retrieving additional globals
*/
CSeat(std::uint32_t globalName, wayland::seat_t const& seat, CConnection& connection);
- ~CSeat() noexcept;
+ virtual ~CSeat() noexcept;
void AddRawInputHandlerKeyboard(IRawInputHandlerKeyboard* rawKeyboardHandler);
void RemoveRawInputHandlerKeyboard(IRawInputHandlerKeyboard* rawKeyboardHandler);
@@ -172,7 +172,13 @@ public:
* Parameters are identical wo wl_pointer.set_cursor().
* If the seat does not currently have the pointer capability, this is a no-op.
*/
- void SetCursor(std::uint32_t serial, wayland::surface_t const& surface, std::int32_t hotspotX, std::int32_t hotspotY);
+ virtual void SetCursor(std::uint32_t serial,
+ wayland::surface_t const& surface,
+ std::int32_t hotspotX,
+ std::int32_t hotspotY);
+
+protected:
+ virtual void InstallKeyboardRepeatInfo();
private:
CSeat(CSeat const& other) = delete;
diff --git a/xbmc/windowing/wayland/SeatWebOS.cpp b/xbmc/windowing/wayland/SeatWebOS.cpp
new file mode 100644
index 0000000000..29eb0117ad
--- /dev/null
+++ b/xbmc/windowing/wayland/SeatWebOS.cpp
@@ -0,0 +1,29 @@
+/*
+* Copyright (C) 2024 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "SeatWebOS.h"
+
+namespace KODI::WINDOWING::WAYLAND
+{
+
+void CSeatWebOS::SetCursor(std::uint32_t serial,
+ wayland::surface_t const& surface,
+ std::int32_t hotspotX,
+ std::int32_t hotspotY)
+{
+ // set_cursor on webOS completely breaks pointer input
+}
+
+void CSeatWebOS::InstallKeyboardRepeatInfo()
+{
+ // Since webOS 7 the compositor sends the following key repeat info:
+ // Key repeat rate: 40 cps, delay 400 ms
+ // Which is too fast for the long press detection
+}
+
+} // namespace KODI::WINDOWING::WAYLAND
diff --git a/xbmc/windowing/wayland/SeatWebOS.h b/xbmc/windowing/wayland/SeatWebOS.h
new file mode 100644
index 0000000000..45bf155f6c
--- /dev/null
+++ b/xbmc/windowing/wayland/SeatWebOS.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (C) 2024 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "Seat.h"
+
+namespace KODI::WINDOWING::WAYLAND
+{
+
+class CSeatWebOS final : public CSeat
+{
+public:
+ CSeatWebOS(std::uint32_t globalName, wayland::seat_t const& seat, CConnection& connection)
+ : CSeat(globalName, seat, connection)
+ {
+ }
+
+ void SetCursor(std::uint32_t serial,
+ wayland::surface_t const& surface,
+ std::int32_t hotspotX,
+ std::int32_t hotspotY) override;
+
+protected:
+ void InstallKeyboardRepeatInfo() override;
+};
+
+} // namespace KODI::WINDOWING::WAYLAND
diff --git a/xbmc/windowing/wayland/WinSystemWayland.cpp b/xbmc/windowing/wayland/WinSystemWayland.cpp
index e226563a35..01d7c8b7ea 100644
--- a/xbmc/windowing/wayland/WinSystemWayland.cpp
+++ b/xbmc/windowing/wayland/WinSystemWayland.cpp
@@ -1088,9 +1088,7 @@ bool CWinSystemWayland::HasCursor()
std::unique_lock<CCriticalSection> lock(m_seatsMutex);
return std::any_of(m_seats.cbegin(), m_seats.cend(),
[](decltype(m_seats)::value_type const& entry)
- {
- return entry.second.HasPointerCapability();
- });
+ { return entry.second->HasPointerCapability(); });
}
void CWinSystemWayland::ShowOSMouse(bool show)
@@ -1144,13 +1142,17 @@ void CWinSystemWayland::OnSeatAdded(std::uint32_t name, wayland::proxy_t&& proxy
std::unique_lock<CCriticalSection> lock(m_seatsMutex);
wayland::seat_t seat(proxy);
- auto newSeatEmplace = m_seats.emplace(std::piecewise_construct,
- std::forward_as_tuple(name),
- std::forward_as_tuple(name, seat, *m_connection));
+ auto newSeatEmplace = m_seats.emplace(std::piecewise_construct, std::forward_as_tuple(name),
+ std::forward_as_tuple(CreateSeat(name, seat)));
auto& seatInst = newSeatEmplace.first->second;
- m_seatInputProcessing->AddSeat(&seatInst);
- m_windowDecorator->AddSeat(&seatInst);
+ m_seatInputProcessing->AddSeat(seatInst.get());
+ m_windowDecorator->AddSeat(seatInst.get());
+}
+
+std::unique_ptr<CSeat> CWinSystemWayland::CreateSeat(std::uint32_t name, wayland::seat_t& seat)
+{
+ return std::make_unique<CSeat>(name, seat, *m_connection);
}
void CWinSystemWayland::OnSeatRemoved(std::uint32_t name)
@@ -1160,8 +1162,8 @@ void CWinSystemWayland::OnSeatRemoved(std::uint32_t name)
auto seatI = m_seats.find(name);
if (seatI != m_seats.end())
{
- m_seatInputProcessing->RemoveSeat(&seatI->second);
- m_windowDecorator->RemoveSeat(&seatI->second);
+ m_seatInputProcessing->RemoveSeat(seatI->second.get());
+ m_windowDecorator->RemoveSeat(seatI->second.get());
m_seats.erase(name);
}
}
@@ -1262,12 +1264,13 @@ void CWinSystemWayland::OnSetCursor(std::uint32_t seatGlobalName, std::uint32_t
LoadDefaultCursor();
if (m_cursorSurface) // Cursor loading could have failed
{
- seatI->second.SetCursor(serial, m_cursorSurface, m_cursorImage.hotspot_x(), m_cursorImage.hotspot_y());
+ seatI->second->SetCursor(serial, m_cursorSurface, m_cursorImage.hotspot_x(),
+ m_cursorImage.hotspot_y());
}
}
else
{
- seatI->second.SetCursor(serial, wayland::surface_t{}, 0, 0);
+ seatI->second->SetCursor(serial, wayland::surface_t{}, 0, 0);
}
}
@@ -1517,7 +1520,7 @@ std::string CWinSystemWayland::GetClipboardText()
// probably just not that relevant in practice
for (auto const& seat : m_seats)
{
- auto text = seat.second.GetSelectionText();
+ auto text = seat.second->GetSelectionText();
if (text != "")
{
return text;
diff --git a/xbmc/windowing/wayland/WinSystemWayland.h b/xbmc/windowing/wayland/WinSystemWayland.h
index 95f2a9cfea..62e96d2183 100644
--- a/xbmc/windowing/wayland/WinSystemWayland.h
+++ b/xbmc/windowing/wayland/WinSystemWayland.h
@@ -122,6 +122,8 @@ protected:
void OnConfigure(std::uint32_t serial, CSizeInt size, IShellSurface::StateBitset state) override;
void OnClose() override;
+ virtual std::unique_ptr<CSeat> CreateSeat(std::uint32_t name, wayland::seat_t& seat);
+
private:
// IInputHandler
void OnEnter(InputType type) override;
@@ -208,7 +210,7 @@ private:
// Seat handling
// -------------
- std::map<std::uint32_t, CSeat> m_seats;
+ std::map<std::uint32_t, std::unique_ptr<CSeat>> m_seats;
CCriticalSection m_seatsMutex;
std::unique_ptr<CSeatInputProcessing> m_seatInputProcessing;
std::map<std::uint32_t, std::shared_ptr<COutput>> m_outputs;
diff --git a/xbmc/windowing/wayland/WinSystemWaylandWebOS.cpp b/xbmc/windowing/wayland/WinSystemWaylandWebOS.cpp
index bfbb2fa286..2ca132026c 100644
--- a/xbmc/windowing/wayland/WinSystemWaylandWebOS.cpp
+++ b/xbmc/windowing/wayland/WinSystemWaylandWebOS.cpp
@@ -11,6 +11,7 @@
#include "Connection.h"
#include "OSScreenSaverWebOS.h"
#include "Registry.h"
+#include "SeatWebOS.h"
#include "ShellSurfaceWebOSShell.h"
#include "application/ApplicationComponents.h"
#include "application/ApplicationPlayer.h"
@@ -148,6 +149,11 @@ std::unique_ptr<KODI::WINDOWING::IOSScreenSaver> CWinSystemWaylandWebOS::GetOSSc
return std::make_unique<COSScreenSaverWebOS>();
}
+std::unique_ptr<CSeat> CWinSystemWaylandWebOS::CreateSeat(std::uint32_t name, wayland::seat_t& seat)
+{
+ return std::make_unique<CSeatWebOS>(name, seat, *GetConnection());
+}
+
bool CWinSystemWaylandWebOS::OnAppLifecycleEventWrapper(LSHandle* sh, LSMessage* reply, void* ctx)
{
HContext* context = static_cast<HContext*>(ctx);
diff --git a/xbmc/windowing/wayland/WinSystemWaylandWebOS.h b/xbmc/windowing/wayland/WinSystemWaylandWebOS.h
index 3f3c9821b4..375b0c3f94 100644
--- a/xbmc/windowing/wayland/WinSystemWaylandWebOS.h
+++ b/xbmc/windowing/wayland/WinSystemWaylandWebOS.h
@@ -50,6 +50,7 @@ public:
protected:
std::unique_ptr<KODI::WINDOWING::IOSScreenSaver> GetOSScreenSaverImpl() override;
+ std::unique_ptr<CSeat> CreateSeat(std::uint32_t name, wayland::seat_t& seat) override;
private:
static bool OnAppLifecycleEventWrapper(LSHandle* sh, LSMessage* reply, void* ctx);
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/GUIWindowFileManager.cpp b/xbmc/windows/GUIWindowFileManager.cpp
index 2093101d08..bf11d13dfe 100644
--- a/xbmc/windows/GUIWindowFileManager.cpp
+++ b/xbmc/windows/GUIWindowFileManager.cpp
@@ -56,9 +56,11 @@
#include "utils/URIUtils.h"
#include "utils/Variant.h"
#include "utils/log.h"
+#include "video/VideoFileItemClassify.h"
using namespace XFILE;
using namespace KODI::MESSAGING;
+using namespace KODI::VIDEO;
#define CONTROL_BTNSELECTALL 1
#define CONTROL_BTNFAVOURITES 2
@@ -655,7 +657,7 @@ void CGUIWindowFileManager::OnStart(CFileItem *pItem, const std::string &player)
g_application.ProcessAndStartPlaylist(strPlayList, *pPlayList, PLAYLIST::TYPE_MUSIC);
return;
}
- if (pItem->IsAudio() || pItem->IsVideo())
+ if (pItem->IsAudio() || IsVideo(*pItem))
{
CServiceBroker::GetPlaylistPlayer().Play(std::make_shared<CFileItem>(*pItem), player);
return;
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"