[vlc-commits] [Git][videolan/vlc][master] 9 commits: medialibrary: Implement functions to acquire movies' media items

Steve Lhomme (@robUx4) gitlab at videolan.org
Tue Jul 15 08:40:47 UTC 2025



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
3c4e671f by Claudio Cambra at 2025-07-15T08:03:36+00:00
medialibrary: Implement functions to acquire movies' media items

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
39c78ae2 by Claudio Cambra at 2025-07-15T08:03:36+00:00
macosx: Implement movies in library model

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
8afb3182 by Claudio Cambra at 2025-07-15T08:03:36+00:00
macosx: Make VLCMediaLibraryMovie compliant with the media library item protocol

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
5ffa77ba by Claudio Cambra at 2025-07-15T08:03:36+00:00
macosx: Add a movies data source

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
31655ebf by Claudio Cambra at 2025-07-15T08:03:36+00:00
macosx: Publicly declare movies reset notification

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
64bd1f68 by Claudio Cambra at 2025-07-15T08:03:36+00:00
macosx: Set up and configure movies view in library video view controller

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
57395561 by Claudio Cambra at 2025-07-15T08:03:36+00:00
macosx: Add movies video library subsegment

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
38e0307c by Claudio Cambra at 2025-07-15T08:03:36+00:00
macosx: Fix handling of groupings table view when handling different video library views

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
85a47054 by Claudio Cambra at 2025-07-15T08:03:36+00:00
medialibrary: Add algorithm include to fix builds on some platforms

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -


16 changed files:

- extras/package/macosx/VLC.xcodeproj/project.pbxproj
- include/vlc_media_library.h
- modules/gui/macosx/Makefile.am
- modules/gui/macosx/library/VLCLibraryDataTypes.h
- modules/gui/macosx/library/VLCLibraryDataTypes.m
- modules/gui/macosx/library/VLCLibraryModel.h
- modules/gui/macosx/library/VLCLibraryModel.m
- modules/gui/macosx/library/VLCLibrarySegment.h
- modules/gui/macosx/library/VLCLibrarySegment.m
- modules/gui/macosx/library/VLCLibraryWindowPersistentPreferences.h
- modules/gui/macosx/library/VLCLibraryWindowPersistentPreferences.m
- + modules/gui/macosx/library/video-library/VLCLibraryMoviesDataSource.h
- + modules/gui/macosx/library/video-library/VLCLibraryMoviesDataSource.m
- modules/gui/macosx/library/video-library/VLCLibraryVideoViewController.h
- modules/gui/macosx/library/video-library/VLCLibraryVideoViewController.m
- modules/misc/medialibrary/medialibrary.cpp


Changes:

=====================================
extras/package/macosx/VLC.xcodeproj/project.pbxproj
=====================================
@@ -174,6 +174,7 @@
 		53F399802AC6D6B400B86241 /* VLCLibraryHomeViewVideoCarouselContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 53F3997F2AC6D6B400B86241 /* VLCLibraryHomeViewVideoCarouselContainerView.m */; };
 		53F7B2372D4D499400F3B38F /* VLCFileDragRecognisingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 53F7B2362D4D499400F3B38F /* VLCFileDragRecognisingView.m */; };
 		53F7B23C2D545FCF00F3B38F /* VLCLibraryAbstractMediaLibrarySegmentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53F7B23B2D545FCF00F3B38F /* VLCLibraryAbstractMediaLibrarySegmentViewController.m */; };
+		53F89E372E23DC4C008080C1 /* VLCLibraryMoviesDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 53F89E362E23DC4C008080C1 /* VLCLibraryMoviesDataSource.m */; };
 		6B0292E61F43256300A50082 /* VLCBottomBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B0292E51F43256300A50082 /* VLCBottomBarView.m */; };
 		6B0AB0F01F1AC8B3003A1B4E /* VLCPlaybackProgressSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B0AB0ED1F1AC8B3003A1B4E /* VLCPlaybackProgressSlider.m */; };
 		6B0AB0F11F1AC8B3003A1B4E /* VLCPlaybackProgressSliderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B0AB0EF1F1AC8B3003A1B4E /* VLCPlaybackProgressSliderCell.m */; };
@@ -527,6 +528,8 @@
 		53F7B2362D4D499400F3B38F /* VLCFileDragRecognisingView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCFileDragRecognisingView.m; sourceTree = "<group>"; };
 		53F7B23A2D545FCF00F3B38F /* VLCLibraryAbstractMediaLibrarySegmentViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCLibraryAbstractMediaLibrarySegmentViewController.h; sourceTree = "<group>"; };
 		53F7B23B2D545FCF00F3B38F /* VLCLibraryAbstractMediaLibrarySegmentViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryAbstractMediaLibrarySegmentViewController.m; sourceTree = "<group>"; };
+		53F89E352E23DC4C008080C1 /* VLCLibraryMoviesDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCLibraryMoviesDataSource.h; sourceTree = "<group>"; };
+		53F89E362E23DC4C008080C1 /* VLCLibraryMoviesDataSource.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryMoviesDataSource.m; sourceTree = "<group>"; };
 		5CCED71014C0D4A90057F8D1 /* VLCExtensionsDialogProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCExtensionsDialogProvider.h; sourceTree = "<group>"; };
 		5CCED71114C0D4A90057F8D1 /* VLCExtensionsDialogProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCExtensionsDialogProvider.m; sourceTree = "<group>"; };
 		5CCED71214C0D4A90057F8D1 /* VLCExtensionsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCExtensionsManager.h; sourceTree = "<group>"; };
@@ -1724,6 +1727,8 @@
 		53B447EB293BB47A00857588 /* video-library */ = {
 			isa = PBXGroup;
 			children = (
+				53F89E352E23DC4C008080C1 /* VLCLibraryMoviesDataSource.h */,
+				53F89E362E23DC4C008080C1 /* VLCLibraryMoviesDataSource.m */,
 				5325720D2C4966630068DEC3 /* VLCLibraryShowsDataSource.h */,
 				5325720E2C4966630068DEC3 /* VLCLibraryShowsDataSource.m */,
 				536EFC37295E521600F4CB13 /* VLCLibraryVideoViewController.h */,
@@ -2406,6 +2411,7 @@
 				6B2EFC631F281A0900F3C0EA /* VLCVolumeSliderCell.m in Sources */,
 				5387FFF52A15127100A3A70A /* NSWindow+VLCAdditions.m in Sources */,
 				1C3113A71E508C6900D4DD76 /* VLCLogWindowController.m in Sources */,
+				53F89E372E23DC4C008080C1 /* VLCLibraryMoviesDataSource.m in Sources */,
 				53F0E930299B17DF00491D49 /* VLCInputNodePathControl.m in Sources */,
 				1C3113A91E508C6900D4DD76 /* VLCDocumentController.m in Sources */,
 				1C3113AB1E508C6900D4DD76 /* VLCExtensionsDialogProvider.m in Sources */,


=====================================
include/vlc_media_library.h
=====================================
@@ -481,6 +481,8 @@ enum vlc_ml_list_queries
     VLC_ML_COUNT_MEDIA,           /**< arg1 (out): size_t*                                                              */
     VLC_ML_LIST_VIDEOS,           /**< arg1 (out): vlc_ml_media_list_t**                                                */
     VLC_ML_COUNT_VIDEOS,          /**< arg1 (out): size_t*                                                              */
+    VLC_ML_LIST_MOVIES,           /**< arg1 (out): vlc_ml_media_list_t**                                                */
+    VLC_ML_COUNT_MOVIES,          /**< arg1 (out): size_t*                                                              */
     VLC_ML_LIST_AUDIOS,           /**< arg1 (out): vlc_ml_media_list_t**                                                */
     VLC_ML_COUNT_AUDIOS,          /**< arg1 (out): size_t*                                                              */
     VLC_ML_LIST_ALBUMS,           /**< arg1 (out): vlc_ml_album_list_t**                                                */
@@ -1661,6 +1663,24 @@ static inline vlc_ml_show_list_t* vlc_ml_list_shows( vlc_medialibrary_t* p_ml, c
     return res;
 }
 
+static inline vlc_ml_media_list_t* vlc_ml_list_movies(vlc_medialibrary_t* p_ml, const vlc_ml_query_params_t* params)
+{
+    vlc_assert(p_ml != NULL);
+    vlc_ml_media_list_t* res;
+    if (vlc_ml_list(p_ml, VLC_ML_LIST_MOVIES, params, &res) != VLC_SUCCESS)
+        return NULL;
+    return res;
+}
+
+static inline size_t vlc_ml_count_movies(vlc_medialibrary_t* p_ml, const vlc_ml_query_params_t* params)
+{
+    vlc_assert(p_ml != NULL);
+    size_t count;
+    if (vlc_ml_list(p_ml, VLC_ML_COUNT_MOVIES, params, &count) != VLC_SUCCESS)
+        return 0;
+    return count;
+}
+
 static inline size_t vlc_ml_count_shows( vlc_medialibrary_t* p_ml, const vlc_ml_query_params_t* params )
 {
     vlc_assert( p_ml != NULL );


=====================================
modules/gui/macosx/Makefile.am
=====================================
@@ -257,6 +257,8 @@ libmacosx_plugin_la_SOURCES = \
     gui/macosx/library/home-library/VLCLibraryHomeViewVideoContainerViewDataSource.m \
 	gui/macosx/library/home-library/VLCLibraryHomeViewVideoGridContainerView.h \
     gui/macosx/library/home-library/VLCLibraryHomeViewVideoGridContainerView.m \
+	gui/macosx/library/video-library/VLCLibraryMoviesDataSource.h \
+	gui/macosx/library/video-library/VLCLibraryMoviesDataSource.m \
 	gui/macosx/library/video-library/VLCLibraryShowsDataSource.h \
 	gui/macosx/library/video-library/VLCLibraryShowsDataSource.m \
 	gui/macosx/library/video-library/VLCLibraryVideoViewController.h \


=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.h
=====================================
@@ -97,15 +97,6 @@ typedef NS_ENUM(NSUInteger, VLCMediaLibraryParentGroupType) {
 
 @end
 
- at interface VLCMediaLibraryMovie : NSObject
-
-- (instancetype)initWithMovie:(struct vlc_ml_movie_t *)p_movie;
-
- at property (readonly) NSString *summary;
- at property (readonly) NSString *imdbID;
-
- at end
-
 @interface VLCMediaLibraryShowEpisode : NSObject
 
 - (instancetype)initWithShowEpisode:(struct vlc_ml_show_episode_t *)p_showEpisode;
@@ -117,8 +108,6 @@ typedef NS_ENUM(NSUInteger, VLCMediaLibraryParentGroupType) {
 
 @end
 
-#pragma mark - Media library classes
-
 @protocol VLCLocallyManipulableItemProtocol <NSObject>
 
 - (void)revealInFinder;
@@ -154,6 +143,12 @@ typedef NS_ENUM(NSUInteger, VLCMediaLibraryParentGroupType) {
 
 @end
 
+// Base abstract class with common implementations of properties used by media library items.
+// Do not use directly -- subclass to create new media library item types.
+ at interface VLCAbstractMediaLibraryItem : NSObject<VLCMediaLibraryItemProtocol>
+
+ at end
+
 // Extended VLCMediaLibraryItemProtocol that includes additional properties for media library item
 // audio groups (i.e. artists, genres, etc.)
 @protocol VLCMediaLibraryAudioGroupProtocol <VLCMediaLibraryItemProtocol>
@@ -168,18 +163,14 @@ typedef NS_ENUM(NSUInteger, VLCMediaLibraryParentGroupType) {
 
 @end
 
-// Base abstract class with common implementations of properties used by media library items.
-// Do not use directly -- subclass to create new media library item types.
- at interface VLCAbstractMediaLibraryItem : NSObject<VLCMediaLibraryItemProtocol>
-
- at end
-
 // Like VLCAbstractMediaLibraryItem but with some additional functionality for audio groupings
 // such as artists and genres. Do not use directly, subclass instead.
 @interface VLCAbstractMediaLibraryAudioGroup : VLCAbstractMediaLibraryItem<VLCMediaLibraryAudioGroupProtocol>
 
 @end
 
+#pragma mark - Media library classes
+
 @interface VLCMediaLibraryArtist : VLCAbstractMediaLibraryAudioGroup<VLCMediaLibraryAudioGroupProtocol>
 
 + (nullable instancetype)artistWithID:(int64_t)artistID;
@@ -231,6 +222,15 @@ typedef NS_ENUM(NSUInteger, VLCMediaLibraryParentGroupType) {
 
 @end
 
+ at interface VLCMediaLibraryMovie : VLCAbstractMediaLibraryItem <VLCMediaLibraryItemProtocol>
+
+- (instancetype)initWithMediaItem:(struct vlc_ml_media_t *)p_media;
+
+ at property (readonly) NSString *summary;
+ at property (readonly) NSString *imdbID;
+
+ at end
+
 @interface VLCMediaLibraryGroup : VLCAbstractMediaLibraryItem
 
 @property (readonly) NSString *name;


=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.m
=====================================
@@ -263,20 +263,6 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
 
 @end
 
- at implementation VLCMediaLibraryMovie
-
-- (instancetype)initWithMovie:(struct vlc_ml_movie_t *)p_movie
-{
-    self = [super init];
-    if (self && p_movie != NULL) {
-        _summary = toNSStr(p_movie->psz_summary);
-        _imdbID = toNSStr(p_movie->psz_imdb_id);
-    }
-    return self;
-}
-
- at end
-
 @implementation VLCMediaLibraryShowEpisode
 
 - (instancetype)initWithShowEpisode:(struct vlc_ml_show_episode_t *)p_showEpisode
@@ -1079,7 +1065,7 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
 
         switch (p_mediaItem->i_subtype) {
             case VLC_ML_MEDIA_SUBTYPE_MOVIE:
-                _movie = [[VLCMediaLibraryMovie alloc] initWithMovie:&p_mediaItem->movie];
+                _movie = [[VLCMediaLibraryMovie alloc] initWithMediaItem:p_mediaItem];
                 break;
 
             case VLC_ML_MEDIA_SUBTYPE_SHOW_EPISODE:
@@ -1634,6 +1620,48 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
 
 @end
 
+ at implementation VLCMediaLibraryMovie
+
+- (instancetype)initWithMediaItem:(struct vlc_ml_media_t *)p_media
+{
+    self = [super init];
+    if (self && p_media != NULL) {
+        // Set up abstract item properties
+        self.libraryID = p_media->i_id;
+        self.smallArtworkGenerated = p_media->thumbnails[VLC_ML_THUMBNAIL_SMALL].psz_mrl != NULL;
+        self.smallArtworkMRL = self.smallArtworkGenerated ? toNSStr(p_media->thumbnails[VLC_ML_THUMBNAIL_SMALL].psz_mrl) : nil;
+        self.displayString = p_media->psz_title ? toNSStr(p_media->psz_title) : @"";
+        self.primaryDetailString = self.displayString;
+        self.secondaryDetailString = @"";
+        self.durationString = [NSString stringWithTime:p_media->i_duration / VLCMediaLibraryMediaItemDurationDenominator];
+
+        // Movie-specific
+        _summary = toNSStr(p_media->movie.psz_summary);
+        _imdbID = toNSStr(p_media->movie.psz_imdb_id);
+    }
+    return self;
+}
+
+- (NSArray<VLCMediaLibraryMediaItem *> *)mediaItems
+{
+    VLCMediaLibraryMediaItem *item = [VLCMediaLibraryMediaItem mediaItemForLibraryID:self.libraryID];
+    return item ? @[item] : @[];
+}
+
+- (VLCMediaLibraryMediaItem *)firstMediaItem
+{
+    return self.mediaItems.firstObject;
+}
+
+- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock
+{
+    for (VLCMediaLibraryMediaItem *item in self.mediaItems) {
+        mediaItemBlock(item);
+    }
+}
+
+ at end
+
 @implementation VLCMediaLibraryEntryPoint
 
 - (instancetype)initWithEntryPoint:(struct vlc_ml_folder_t *)p_entryPoint


=====================================
modules/gui/macosx/library/VLCLibraryModel.h
=====================================
@@ -44,6 +44,7 @@ extern NSString * const VLCLibraryModelFavoriteGenresListReset;
 extern NSString * const VLCLibraryModelRecentsMediaListReset;
 extern NSString * const VLCLibraryModelRecentAudioMediaListReset;
 extern NSString * const VLCLibraryModelListOfShowsReset;
+extern NSString * const VLCLibraryModelListOfMoviesReset;
 extern NSString * const VLCLibraryModelListOfGroupsReset;
 
 extern NSString * const VLCLibraryModelAudioMediaItemDeleted;
@@ -105,6 +106,9 @@ extern NSString * const VLCLibraryModelDiscoveryFailed;
 @property (readonly) size_t numberOfShows;
 @property (readonly) NSArray <VLCMediaLibraryShow *> *listOfShows;
 
+ at property (readonly) size_t numberOfMovies;
+ at property (readonly) NSArray <VLCMediaLibraryMovie *> *listOfMovies;
+
 @property (readonly) size_t numberOfGroups;
 @property (readonly) NSArray <VLCMediaLibraryGroup *> *listOfGroups;
 


=====================================
modules/gui/macosx/library/VLCLibraryModel.m
=====================================
@@ -45,6 +45,7 @@ NSString * const VLCLibraryModelFavoriteGenresListReset = @"VLCLibraryModelFavor
 NSString * const VLCLibraryModelRecentsMediaListReset = @"VLCLibraryModelRecentsMediaListReset";
 NSString * const VLCLibraryModelRecentAudioMediaListReset = @"VLCLibraryModelRecentAudioMediaListReset";
 NSString * const VLCLibraryModelListOfShowsReset = @"VLCLibraryModelListOfShowsReset";
+NSString * const VLCLibraryModelListOfMoviesReset = @"VLCLibraryModelListOfMoviesReset";
 NSString * const VLCLibraryModelListOfGroupsReset = @"VLCLibraryModelListOfGroupsReset";
 
 NSString * const VLCLibraryModelPlaylistAdded = @"VLCLibraryModelPlaylistAdded";
@@ -90,6 +91,7 @@ NSString * const VLCLibraryModelDiscoveryFailed = @"VLCLibraryModelDiscoveryFail
     size_t _initialArtistCount;
     size_t _initialGenreCount;
     size_t _initialShowCount;
+    size_t _initialMovieCount;
     size_t _initialGroupCount;
     size_t _initialRecentsCount;
     size_t _initialRecentAudioCount;
@@ -109,6 +111,7 @@ NSString * const VLCLibraryModelDiscoveryFailed = @"VLCLibraryModelDiscoveryFail
 @property (readwrite, atomic) NSArray *cachedGenres;
 @property (readwrite, atomic) NSArray *cachedVideoMedia;
 @property (readwrite, atomic) NSArray *cachedListOfShows;
+ at property (readwrite, atomic) NSArray *cachedListOfMovies;
 @property (readwrite, atomic) NSArray *cachedListOfGroups;
 @property (readwrite, atomic) NSArray *cachedRecentMedia;
 @property (readwrite, atomic) NSArray *cachedRecentAudioMedia;
@@ -321,6 +324,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
             self->_initialArtistCount = vlc_ml_count_artists(self->_p_mediaLibrary, &queryParameters, true);
             self->_initialGenreCount = vlc_ml_count_genres(self->_p_mediaLibrary, &queryParameters);
             self->_initialShowCount = vlc_ml_count_shows(self->_p_mediaLibrary, &queryParameters);
+            self->_initialMovieCount = vlc_ml_count_movies(self->_p_mediaLibrary, &queryParameters);
             self->_initialGroupCount = vlc_ml_count_groups(self->_p_mediaLibrary, &queryParameters);
 
             queryParameters.i_nbResults = self->_recentMediaLimit;
@@ -672,6 +676,34 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     });
 }
 
+- (void)resetCachedListOfMovies
+{
+    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
+        vlc_ml_media_list_t * const p_movie_list = vlc_ml_list_movies(self->_p_mediaLibrary, NULL);
+        if (p_movie_list == NULL) {
+            return;
+        }
+        const size_t itemCount = p_movie_list->i_nb_items;
+        NSMutableArray * const mutableArray = [[NSMutableArray alloc] initWithCapacity:itemCount];
+        for (size_t x = 0; x < p_movie_list->i_nb_items; x++) {
+            vlc_ml_media_t * const p_vlc_media = &p_movie_list->p_items[x];
+            // Defensive: only add if subtype is MOVIE
+            if (p_vlc_media->i_subtype == VLC_ML_MEDIA_SUBTYPE_MOVIE) {
+                VLCMediaLibraryMovie * const movie = [[VLCMediaLibraryMovie alloc] initWithMediaItem:p_vlc_media];
+                if (movie) {
+                    [mutableArray addObject:movie];
+                }
+            }
+        }
+        vlc_ml_media_list_release(p_movie_list);
+        dispatch_async(dispatch_get_main_queue(), ^{
+            self.cachedListOfMovies = mutableArray.copy;
+            [self.changeDelegate notifyChange:VLCLibraryModelListOfMoviesReset withObject:self];
+            [NSNotificationCenter.defaultCenter postNotificationName:VLCLibraryModelListOfMoviesReset object:self];
+        });
+    });
+}
+
 - (size_t)numberOfShows
 {
     if (!_cachedListOfShows) {
@@ -682,6 +714,16 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     return _cachedListOfShows.count;
 }
 
+- (size_t)numberOfMovies
+{
+    if (!_cachedListOfMovies) {
+        [self resetCachedListOfMovies];
+        // Return initial count here, otherwise it will return 0 on the first time
+        return _initialMovieCount;
+    }
+    return _cachedListOfMovies.count;
+}
+
 - (NSArray<VLCMediaLibraryShow *> *)listOfShows
 {
     if (!_cachedListOfShows) {
@@ -690,6 +732,14 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     return _cachedListOfShows;
 }
 
+- (NSArray<VLCMediaLibraryMovie *> *)listOfMovies
+{
+    if (!_cachedListOfMovies) {
+        [self resetCachedListOfMovies];
+    }
+    return _cachedListOfMovies;
+}
+
 - (size_t)numberOfGroups
 {
     if (!_cachedListOfGroups) {


=====================================
modules/gui/macosx/library/VLCLibrarySegment.h
=====================================
@@ -37,6 +37,7 @@ typedef NS_ENUM(NSInteger, VLCLibrarySegmentType) {
     VLCLibraryHeaderSegmentType,
     VLCLibraryVideoSegmentType,
     VLCLibraryShowsVideoSubSegmentType,
+    VLCLibraryMoviesVideoSubSegmentType,
     VLCLibraryMusicSegmentType,
     VLCLibraryArtistsMusicSubSegmentType,
     VLCLibraryAlbumsMusicSubSegmentType,


=====================================
modules/gui/macosx/library/VLCLibrarySegment.m
=====================================
@@ -209,6 +209,43 @@ NSArray<NSString *> *defaultBookmarkedLocations()
 @interface VLCLibraryVideoShowsSubSegment : VLCLibrarySegment
 @end
 
+ at interface VLCLibraryVideoMoviesSubSegment : VLCLibrarySegment
+ at end
+
+ at implementation VLCLibraryVideoMoviesSubSegment
+
+- (instancetype)init
+{
+    self = [super initWithSegmentType:VLCLibraryMoviesVideoSubSegmentType];
+    if (self) {
+        self.internalDisplayString = _NS("Movies");
+        if (@available(macOS 11.0, *)) {
+            self.internalDisplayImage = [NSImage imageWithSystemSymbolName:@"film"
+                                                  accessibilityDescription:@"Movies icon"];
+        } else {
+            self.internalDisplayImage = [NSImage imageNamed:@"sidebar-movie"];
+            self.internalDisplayImage.template = YES;
+        }
+        self.internalLibraryViewControllerClass = VLCLibraryVideoViewController.class;
+        self.internalLibraryViewControllerCreator = ^{
+            return [[VLCLibraryVideoViewController alloc] initWithLibraryWindow:VLCMain.sharedInstance.libraryWindow];
+        };
+        self.internalLibraryViewPresenter = ^(VLCLibraryAbstractSegmentViewController * const controller) {
+            [(VLCLibraryVideoViewController *)controller presentMoviesView];
+        };
+        self.internalSaveViewModePreference = ^(const NSInteger viewMode) {
+            VLCLibraryWindowPersistentPreferences.sharedInstance.moviesLibraryViewMode = viewMode;
+        };
+        self.internalGetViewModePreference = ^{
+            return VLCLibraryWindowPersistentPreferences.sharedInstance.moviesLibraryViewMode;
+        };
+        self.internalToolbarDisplayFlags = standardLibraryViewToolbarDisplayFlags;
+    }
+    return self;
+}
+
+ at end
+
 @implementation VLCLibraryVideoShowsSubSegment
 
 - (instancetype)init
@@ -275,7 +312,10 @@ NSArray<NSString *> *defaultBookmarkedLocations()
             return VLCLibraryWindowPersistentPreferences.sharedInstance.videoLibraryViewMode;
         };
         self.internalToolbarDisplayFlags = standardLibraryViewToolbarDisplayFlags;
-        self.internalChildNodes = @[[[VLCLibraryVideoShowsSubSegment alloc] init]];
+        self.internalChildNodes = @[
+            [[VLCLibraryVideoShowsSubSegment alloc] init],
+            [[VLCLibraryVideoMoviesSubSegment alloc] init]
+        ];
     }
     return self;
 }
@@ -877,6 +917,8 @@ NSArray<NSString *> *defaultBookmarkedLocations()
             return [[VLCLibraryVideoSegment alloc] init];
         case VLCLibraryShowsVideoSubSegmentType:
             return [[VLCLibraryVideoShowsSubSegment alloc] init];
+        case VLCLibraryMoviesVideoSubSegmentType:
+            return [[VLCLibraryVideoMoviesSubSegment alloc] init];
         case VLCLibraryMusicSegmentType:
             return [[VLCLibraryMusicSegment alloc] init];
         case VLCLibraryArtistsMusicSubSegmentType:
@@ -923,6 +965,8 @@ NSArray<NSString *> *defaultBookmarkedLocations()
     } else if (validMediaItem && mediaItem.mediaType == VLC_ML_MEDIA_TYPE_VIDEO) {
         if (mediaItem.mediaSubType == VLC_ML_MEDIA_SUBTYPE_SHOW_EPISODE) {
             return [VLCLibrarySegment segmentWithSegmentType:VLCLibraryShowsVideoSubSegmentType];
+        } else if (mediaItem.mediaSubType == VLC_ML_MEDIA_SUBTYPE_MOVIE) {
+            return [VLCLibrarySegment segmentWithSegmentType:VLCLibraryMoviesVideoSubSegmentType];
         }
         return [VLCLibrarySegment segmentWithSegmentType:VLCLibraryVideoSegmentType];
     }


=====================================
modules/gui/macosx/library/VLCLibraryWindowPersistentPreferences.h
=====================================
@@ -34,6 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (readwrite, nonatomic) VLCLibraryViewModeSegment favoritesLibraryViewMode;
 @property (readwrite, nonatomic) VLCLibraryViewModeSegment videoLibraryViewMode;
 @property (readwrite, nonatomic) VLCLibraryViewModeSegment showsLibraryViewMode;
+ at property (readwrite, nonatomic) VLCLibraryViewModeSegment moviesLibraryViewMode;
 @property (readwrite, nonatomic) VLCLibraryViewModeSegment albumLibraryViewMode;
 @property (readwrite, nonatomic) VLCLibraryViewModeSegment genreLibraryViewMode;
 @property (readwrite, nonatomic) VLCLibraryViewModeSegment songsLibraryViewMode;


=====================================
modules/gui/macosx/library/VLCLibraryWindowPersistentPreferences.m
=====================================
@@ -28,6 +28,7 @@ NSString * const VLCLibraryHomeLibraryViewModePreferenceKey = @"HomeLibraryViewM
 NSString * const VLCLibraryFavoritesLibraryViewModePreferenceKey = @"FavoritesLibraryViewMode";
 NSString * const VLCLibraryVideoLibraryViewModePreferenceKey = @"VideoLibraryViewMode";
 NSString * const VLCLibraryShowsLibraryViewModePreferenceKey = @"ShowsLibraryViewMode";
+NSString * const VLCLibraryMoviesLibraryViewModePreferenceKey = @"MoviesLibraryViewMode";
 NSString * const VLCLibraryAlbumLibraryViewModePreferenceKey = @"AlbumLibraryViewMode";
 NSString * const VLCLibraryGenreLibraryViewModePreferenceKey = @"GenreLibraryViewMode";
 NSString * const VLCLibrarySongsLibraryViewModePreferenceKey = @"SongsLibraryViewMode";
@@ -131,6 +132,17 @@ static VLCLibraryWindowPersistentPreferences *sharedInstance = nil;
                                               value:showsLibraryViewMode];
 }
 
+- (VLCLibraryViewModeSegment)moviesLibraryViewMode
+{
+    return [self libraryViewModePreferenceWithKey:VLCLibraryMoviesLibraryViewModePreferenceKey];
+}
+
+- (void)setMoviesLibraryViewMode:(VLCLibraryViewModeSegment)moviesLibraryViewMode
+{
+    [self setLibraryWindowViewModePreferenceWithKey:VLCLibraryMoviesLibraryViewModePreferenceKey
+                                              value:moviesLibraryViewMode];
+}
+
 - (VLCLibraryViewModeSegment)albumLibraryViewMode
 {
     return [self libraryViewModePreferenceWithKey:VLCLibraryAlbumLibraryViewModePreferenceKey];


=====================================
modules/gui/macosx/library/video-library/VLCLibraryMoviesDataSource.h
=====================================
@@ -0,0 +1,40 @@
+/*****************************************************************************
+ * VLCLibraryMoviesDataSource.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <developer at claudiocambra.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+#import "library/VLCLibraryCollectionViewDataSource.h"
+#import "library/VLCLibraryTableViewDataSource.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+ at class VLCLibraryModel;
+
+ at interface VLCLibraryMoviesDataSource : NSObject <VLCLibraryCollectionViewDataSource, VLCLibraryTableViewDataSource>
+
+ at property (readwrite, weak) VLCLibraryModel *libraryModel;
+ at property (readwrite, weak) NSCollectionView *collectionView;
+ at property (readwrite, weak) NSTableView *tableView;
+
+ at end
+
+NS_ASSUME_NONNULL_END


=====================================
modules/gui/macosx/library/video-library/VLCLibraryMoviesDataSource.m
=====================================
@@ -0,0 +1,166 @@
+/*****************************************************************************
+ * VLCLibraryMoviesDataSource.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <developer at claudiocambra.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import "VLCLibraryMoviesDataSource.h"
+#import "library/VLCLibraryModel.h"
+#import "library/VLCLibraryRepresentedItem.h"
+#import "library/VLCLibraryCollectionViewMediaItemSupplementaryDetailView.h"
+#import "library/VLCLibraryCollectionViewItem.h"
+
+NSString * const VLCLibraryMoviesDataSourceDisplayedCollectionChangedNotification = @"VLCLibraryMoviesDataSourceDisplayedCollectionChangedNotification";
+
+ at implementation VLCLibraryMoviesDataSource
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        [self connect];
+    }
+    return self;
+}
+
+- (void)connect
+{
+    NSNotificationCenter * const notificationCenter = NSNotificationCenter.defaultCenter;
+    [notificationCenter addObserver:self
+                           selector:@selector(libraryModelMoviesListReset:)
+                               name:VLCLibraryModelListOfMoviesReset
+                             object:nil];
+    [self reloadData];
+}
+
+- (void)disconnect
+{
+    [NSNotificationCenter.defaultCenter removeObserver:self];
+}
+
+- (void)libraryModelMoviesListReset:(NSNotification *)notification
+{
+    [self reloadData];
+}
+
+#pragma mark - NSCollectionViewDataSource
+
+- (NSInteger)numberOfSectionsInCollectionView:(NSCollectionView *)collectionView
+{
+    return 1;
+}
+
+- (NSInteger)collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
+{
+    return self.libraryModel.numberOfMovies;
+}
+
+- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath
+{
+    VLCLibraryCollectionViewItem * const item = [collectionView makeItemWithIdentifier:VLCLibraryCellIdentifier forIndexPath:indexPath];
+    const id<VLCMediaLibraryItemProtocol> movie = [self libraryItemAtIndexPath:indexPath forCollectionView:collectionView];
+    VLCLibraryRepresentedItem * const representedItem = [[VLCLibraryRepresentedItem alloc] initWithItem:movie parentType:self.currentParentType];
+    item.representedItem = representedItem;
+    return item;
+}
+
+- (NSView *)collectionView:(NSCollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
+{
+    if ([kind isEqualToString:VLCLibraryCollectionViewMediaItemSupplementaryDetailViewKind]) {
+        VLCLibraryCollectionViewMediaItemSupplementaryDetailView * const detailView =
+            [collectionView makeSupplementaryViewOfKind:kind
+                                         withIdentifier:VLCLibraryCollectionViewMediaItemSupplementaryDetailViewKind
+                                           forIndexPath:indexPath];
+        const id<VLCMediaLibraryItemProtocol> movie = [self libraryItemAtIndexPath:indexPath forCollectionView:collectionView];
+        VLCLibraryRepresentedItem * const representedItem = [[VLCLibraryRepresentedItem alloc] initWithItem:movie parentType:self.currentParentType];
+        detailView.representedItem = representedItem;
+        detailView.selectedItem = [collectionView itemAtIndexPath:indexPath];
+        return detailView;
+    }
+    return nil;
+}
+
+#pragma mark - VLCLibraryCollectionViewDataSource
+
+- (id<VLCMediaLibraryItemProtocol>)libraryItemAtIndexPath:(NSIndexPath *)indexPath forCollectionView:(NSCollectionView *)collectionView
+{
+    return self.libraryModel.listOfMovies[indexPath.item];
+}
+
+- (NSIndexPath *)indexPathForLibraryItem:(id<VLCMediaLibraryItemProtocol>)libraryItem
+{
+    const NSUInteger idx = [self.libraryModel.listOfMovies indexOfObject:libraryItem];
+    if (idx == NSNotFound) return nil;
+    return [NSIndexPath indexPathForItem:idx inSection:0];
+}
+
+- (NSArray<VLCLibraryRepresentedItem *> *)representedItemsAtIndexPaths:(NSSet<NSIndexPath *> *const)indexPaths forCollectionView:(NSCollectionView *)collectionView
+{
+    NSMutableArray * const items = [NSMutableArray arrayWithCapacity:indexPaths.count];
+    for (NSIndexPath * const indexPath in indexPaths) {
+        const id<VLCMediaLibraryItemProtocol> item = [self libraryItemAtIndexPath:indexPath forCollectionView:collectionView];
+        if (item) {
+            [items addObject:[[VLCLibraryRepresentedItem alloc] initWithItem:item parentType:self.currentParentType]];
+        }
+    }
+    return items;
+}
+
+- (NSString *)supplementaryDetailViewKind
+{
+    return VLCLibraryCollectionViewMediaItemSupplementaryDetailViewKind;
+}
+
+- (void)reloadData
+{
+    // Notify all attached views to reload their data
+    if (self.collectionView) {
+        [self.collectionView reloadData];
+    }
+    if (self.tableView) {
+        [self.tableView reloadData];
+    }
+    [NSNotificationCenter.defaultCenter postNotificationName:VLCLibraryMoviesDataSourceDisplayedCollectionChangedNotification
+                                                      object:self
+                                                    userInfo:nil];
+}
+
+#pragma mark - VLCLibraryTableViewDataSource
+
+- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
+{
+    return self.libraryModel.numberOfMovies;
+}
+
+- (id<VLCMediaLibraryItemProtocol>)libraryItemAtRow:(NSInteger)row forTableView:(nullable NSTableView *)tableView
+{
+    return self.libraryModel.listOfMovies[row];
+}
+
+- (NSInteger)rowForLibraryItem:(id<VLCMediaLibraryItemProtocol>)libraryItem
+{
+    return [self.libraryModel.listOfMovies indexOfObject:libraryItem];
+}
+
+- (VLCMediaLibraryParentGroupType)currentParentType
+{
+    return VLCMediaLibraryParentGroupTypeVideoLibrary;
+}
+
+ at end


=====================================
modules/gui/macosx/library/video-library/VLCLibraryVideoViewController.h
=====================================
@@ -29,6 +29,7 @@
 @class VLCLibraryWindow;
 @class VLCLibraryVideoDataSource;
 @class VLCLibraryShowsDataSource;
+ at class VLCLibraryMoviesDataSource;
 
 @protocol VLCMediaLibraryItemProtocol;
 
@@ -48,10 +49,12 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (readonly, nullable) VLCLibraryVideoDataSource *libraryVideoDataSource;
 @property (readonly, nullable) VLCLibraryShowsDataSource *libraryShowsDataSource;
+ at property (readonly, nullable) VLCLibraryMoviesDataSource *libraryMoviesDataSource;
 
 - (instancetype)initWithLibraryWindow:(VLCLibraryWindow *)libraryWindow;
 - (void)presentVideoView;
 - (void)presentShowsView;
+- (void)presentMoviesView;
 - (void)presentLibraryItem:(id<VLCMediaLibraryItemProtocol>)libraryItem;
 
 @end


=====================================
modules/gui/macosx/library/video-library/VLCLibraryVideoViewController.m
=====================================
@@ -48,6 +48,7 @@
 #import "library/video-library/VLCLibraryShowsDataSource.h"
 #import "library/video-library/VLCLibraryVideoDataSource.h"
 #import "library/video-library/VLCLibraryVideoTableViewDelegate.h"
+#import "library/video-library/VLCLibraryMoviesDataSource.h"
 
 #import "main/VLCMain.h"
 
@@ -166,6 +167,15 @@
     self.libraryShowsDataSource.detailTableView = self.videoLibraryGroupSelectionTableView;
 }
 
+- (void)setupMoviesDataSource
+{
+    _libraryMoviesDataSource = [[VLCLibraryMoviesDataSource alloc] init];
+    self.libraryMoviesDataSource.libraryModel =
+        VLCMain.sharedInstance.libraryController.libraryModel;
+    self.libraryMoviesDataSource.tableView = self.videoLibraryGroupSelectionTableView;
+    self.libraryMoviesDataSource.collectionView = self.videoLibraryCollectionView;
+}
+
 - (void)setupCollectionView
 {
     _collectionViewLayout = [[VLCLibraryCollectionViewFlowLayout alloc] init];
@@ -256,6 +266,8 @@
         return self.libraryVideoDataSource;
     } else if (librarySegmentType == VLCLibraryShowsVideoSubSegmentType) {
         return self.libraryShowsDataSource;
+    } else if (librarySegmentType == VLCLibraryMoviesVideoSubSegmentType) {
+        return self.libraryMoviesDataSource;
     } else {
         return nil;
     }
@@ -264,12 +276,14 @@
 - (void)updatePresentedVideoLibraryView
 {
     _libraryShowsDataSource = nil;
+    _libraryMoviesDataSource = nil;
     [self setupVideoDataSource];
     self.videoLibraryCollectionView.dataSource = self.libraryVideoDataSource;
 
     self.videoLibraryGroupsTableView.dataSource = self.libraryVideoDataSource;
     self.videoLibraryGroupsTableView.target = self.libraryVideoDataSource;
     self.videoLibraryGroupsTableView.delegate = _videoLibraryTableViewDelegate;
+    self.videoLibraryGroupsTableViewScrollView.hidden = NO;
 
     self.videoLibraryGroupSelectionTableView.dataSource = self.libraryVideoDataSource;
     self.videoLibraryGroupSelectionTableView.target = self.libraryVideoDataSource;
@@ -291,12 +305,14 @@
 - (void)updatePresentedShowsLibraryView
 {
     _libraryVideoDataSource = nil;
+    _libraryMoviesDataSource = nil;
     [self setupShowsDataSource];
     self.videoLibraryCollectionView.dataSource = self.libraryShowsDataSource;
 
     self.videoLibraryGroupsTableView.dataSource = self.libraryShowsDataSource;
     self.videoLibraryGroupsTableView.target = self.libraryShowsDataSource;
     self.videoLibraryGroupsTableView.delegate = _videoLibraryTableViewDelegate;
+    self.videoLibraryGroupsTableViewScrollView.hidden = NO;
 
     self.videoLibraryGroupSelectionTableView.dataSource = self.libraryShowsDataSource;
     self.videoLibraryGroupSelectionTableView.target = self.libraryShowsDataSource;
@@ -320,6 +336,40 @@
     [self updatePresentedVideoLibraryView];
 }
 
+- (void)updatePresentedMoviesLibraryView
+{
+    _libraryVideoDataSource = nil;
+    _libraryShowsDataSource = nil;
+    [self setupMoviesDataSource];
+    self.videoLibraryCollectionView.dataSource = self.libraryMoviesDataSource;
+
+    self.videoLibraryGroupsTableView.dataSource = nil;
+    self.videoLibraryGroupsTableView.target = nil;
+    self.videoLibraryGroupsTableView.delegate = nil;
+    self.videoLibraryGroupsTableViewScrollView.hidden = YES;
+
+    self.videoLibraryGroupSelectionTableView.dataSource = self.libraryMoviesDataSource;
+    self.videoLibraryGroupSelectionTableView.target = self.libraryMoviesDataSource;
+    self.videoLibraryGroupSelectionTableView.delegate = _videoLibraryTableViewDelegate;
+
+    [self.libraryMoviesDataSource reloadData];
+
+    const BOOL anyMovies = self.libraryMoviesDataSource.libraryModel.numberOfMovies > 0;
+    if (anyMovies) {
+        const VLCLibraryViewModeSegment viewModeSegment = VLCLibraryWindowPersistentPreferences.sharedInstance.moviesLibraryViewMode;
+        [self presentVideoLibraryView:viewModeSegment];
+    } else if (self.libraryMoviesDataSource.libraryModel.filterString.length > 0) {
+        [self.libraryWindow displayNoResultsMessage];
+    } else {
+        [self presentPlaceholderVideoLibraryView];
+    }
+}
+
+- (void)presentMoviesView
+{
+    [self updatePresentedMoviesLibraryView];
+}
+
 - (void)presentShowsView
 {
     [self updatePresentedShowsLibraryView];
@@ -365,6 +415,12 @@
          self.libraryWindow.videoViewController.view.hidden) {
 
          [self updatePresentedShowsLibraryView];
+     } else if (self.libraryWindow.librarySegmentType == VLCLibraryMoviesVideoSubSegmentType &&
+         ((model.numberOfMovies == 0 && ![self.libraryTargetView.subviews containsObject:self.emptyLibraryView]) ||
+          (model.numberOfMovies > 0 && ![self.libraryTargetView.subviews containsObject:_videoLibraryView])) &&
+         self.libraryWindow.videoViewController.view.hidden) {
+
+         [self updatePresentedMoviesLibraryView];
      }
 }
 


=====================================
modules/misc/medialibrary/medialibrary.cpp
=====================================
@@ -43,6 +43,7 @@
 #include <medialibrary/IBookmark.h>
 #include <medialibrary/IFolder.h>
 
+#include <algorithm>
 #include <sstream>
 #include <initializer_list>
 
@@ -1019,6 +1020,49 @@ int MediaLibrary::List( int listQuery, const vlc_ml_query_params_t* params, va_l
             *va_arg( args, size_t* ) = query->count();
             break;
         }
+        case VLC_ML_LIST_MOVIES:
+        {
+            medialibrary::Query<medialibrary::IMedia> query;
+            if ( psz_pattern != nullptr )
+                query = m_ml->searchVideo( psz_pattern, paramsPtr );
+            else
+                query = m_ml->videoFiles( paramsPtr );
+            if ( query == nullptr )
+                return VLC_EGENERIC;
+            // Filter for movies only
+            auto items = query->items(nbItems, offset);
+            items.erase(
+                std::remove_if(
+                    items.begin(),
+                    items.end(),
+                    [](const auto& item) {
+                        return item->subType() != medialibrary::IMedia::SubType::Movie;
+                    }),
+                items.end());
+            const auto res = ml_convert_list<vlc_ml_media_list_t, vlc_ml_media_t>(items);
+            *va_arg( args, vlc_ml_media_list_t**) = res;
+            break;
+        }
+        case VLC_ML_COUNT_MOVIES:
+        {
+            medialibrary::Query<medialibrary::IMedia> query;
+            if ( psz_pattern != nullptr )
+                query = m_ml->searchVideo( psz_pattern, paramsPtr );
+            else
+                query = m_ml->videoFiles( paramsPtr );
+            if ( query == nullptr )
+                return VLC_EGENERIC;
+            // Filter for movies only
+            const auto items = query->items( 0, 0 );
+            const size_t count = std::count_if(
+                items.cbegin(),
+                items.cend(),
+                [](const auto& item) {
+                    return item->subType() == medialibrary::IMedia::SubType::Movie;
+                });
+            *va_arg( args, size_t* ) = count;
+            break;
+        }
         case VLC_ML_LIST_AUDIOS:
         {
             medialibrary::Query<medialibrary::IMedia> query;



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/0351db7f2fd75d634f637d8091c6592caab7c5cf...85a47054a970c100302bf68cb69b724c676e9175

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/0351db7f2fd75d634f637d8091c6592caab7c5cf...85a47054a970c100302bf68cb69b724c676e9175
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list