[vlc-commits] [Git][videolan/vlc][master] 5 commits: macosx: Avoid blocking main and global queues when acquiring thumbnails
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Sat Jul 4 18:01:57 UTC 2026
Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC
Commits:
bb49ee7a by Claudio Cambra at 2026-07-04T19:38:03+02:00
macosx: Avoid blocking main and global queues when acquiring thumbnails
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
ecc44894 by Claudio Cambra at 2026-07-04T19:38:03+02:00
macosx: Limit thumbnail image generation iteration to expected composite image count
Avoid unneeded work
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
9fffe2ab by Claudio Cambra at 2026-07-04T19:38:03+02:00
macosx: Deduplicate iterateMediaItemsWithBlock implementations
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
bd3ff021 by Claudio Cambra at 2026-07-04T19:38:03+02:00
macosx: Add enumeration of media items method with stop parameter
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
43d24a49 by Claudio Cambra at 2026-07-04T19:38:03+02:00
macosx: Avoid duplicates an no-art images in composite images
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
4 changed files:
- modules/gui/macosx/library/VLCLibraryDataTypes.h
- modules/gui/macosx/library/VLCLibraryDataTypes.m
- modules/gui/macosx/library/VLCLibraryImageCache.m
- modules/gui/macosx/library/audio-library/VLCLibraryAllAudioGroupsMediaLibraryItem.m
Changes:
=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.h
=====================================
@@ -144,6 +144,7 @@ typedef NS_ENUM(NSUInteger, VLCMediaLibraryParentGroupType) {
- (int)setFavorite:(BOOL)favorite;
- (int)toggleFavorite;
+- (void)enumerateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem *item, BOOL *stop))mediaItemBlock;
- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock;
@end
=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.m
=====================================
@@ -366,9 +366,22 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
[self.firstMediaItem revealInFinder];
}
+- (void)enumerateMediaItemsWithBlock:(nonnull void (^)(VLCMediaLibraryMediaItem * _Nonnull, BOOL * _Nonnull))mediaItemBlock
+{
+ for (VLCMediaLibraryMediaItem * const item in self.mediaItems) {
+ BOOL stop = NO;
+ mediaItemBlock(item, &stop);
+ if (stop) {
+ break;
+ }
+ }
+}
+
- (void)iterateMediaItemsWithBlock:(nonnull void (^)(VLCMediaLibraryMediaItem * _Nonnull))mediaItemBlock
{
- [self doesNotRecognizeSelector:_cmd];
+ [self enumerateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item, BOOL * const stop) {
+ mediaItemBlock(item);
+ }];
}
- (NSArray<NSString *> *)labels
@@ -582,8 +595,28 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock
{
- for(VLCMediaLibraryAlbum* album in self.albums) {
- [album iterateMediaItemsWithBlock:mediaItemBlock];
+ [self enumerateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item, BOOL * const stop) {
+ mediaItemBlock(item);
+ }];
+}
+
+- (void)enumerateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem *item, BOOL *stop))mediaItemBlock
+{
+ __block BOOL shouldStop = NO;
+ for (VLCMediaLibraryAlbum * const album in self.albums) {
+ if (shouldStop) {
+ break;
+ }
+ [album enumerateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item, BOOL * const stop) {
+ if (shouldStop) {
+ *stop = YES;
+ return;
+ }
+ mediaItemBlock(item, stop);
+ if (*stop) {
+ shouldStop = YES;
+ }
+ }];
}
}
@@ -708,13 +741,6 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
return self.genres.firstObject;
}
-- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock
-{
- for(VLCMediaLibraryMediaItem* mediaItem in self.mediaItems) {
- mediaItemBlock(mediaItem);
- }
-}
-
- (int)setFavorite:(BOOL)favorite
{
const int res = setFavoriteForLibraryItem(vlc_ml_album_set_favorite, self.libraryID, favorite);
@@ -805,10 +831,25 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock
{
// By default iterate album-by-album
- [self iterateMediaItemsWithBlock:mediaItemBlock orderedBy:VLC_ML_PARENT_ALBUM];
+ [self enumerateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item, BOOL * const stop) {
+ mediaItemBlock(item);
+ } orderedBy:VLC_ML_PARENT_ALBUM];
+}
+
+- (void)enumerateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem *item, BOOL *stop))mediaItemBlock
+{
+ [self enumerateMediaItemsWithBlock:mediaItemBlock orderedBy:VLC_ML_PARENT_ALBUM];
}
- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock orderedBy:(int)mediaItemParentType
+{
+ [self enumerateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item, BOOL * const stop) {
+ mediaItemBlock(item);
+ } orderedBy:mediaItemParentType];
+}
+
+- (void)enumerateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem *item, BOOL *stop))mediaItemBlock
+ orderedBy:(int)mediaItemParentType
{
NSArray<id<VLCMediaLibraryItemProtocol>> *childItems;
switch(mediaItemParentType) {
@@ -824,8 +865,21 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
break;
}
- for(id<VLCMediaLibraryItemProtocol> childItem in childItems) {
- [childItem iterateMediaItemsWithBlock:mediaItemBlock];
+ __block BOOL shouldStop = NO;
+ for (id<VLCMediaLibraryItemProtocol> const childItem in childItems) {
+ if (shouldStop) {
+ break;
+ }
+ [childItem enumerateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item, BOOL * const stop) {
+ if (shouldStop) {
+ *stop = YES;
+ return;
+ }
+ mediaItemBlock(item, stop);
+ if (*stop) {
+ shouldStop = YES;
+ }
+ }];
}
}
@@ -922,13 +976,6 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
return self.groupMediaItems;
}
-- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock
-{
- for (VLCMediaLibraryMediaItem * const item in self.mediaItems) {
- [item iterateMediaItemsWithBlock:mediaItemBlock];
- }
-}
-
@end
@interface VLCMediaLibraryPlaylist ()
@@ -1131,17 +1178,6 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
}
}
-- (void)iterateMediaItemsWithBlock:(nonnull void (^)(VLCMediaLibraryMediaItem * _Nonnull))mediaItemBlock
-{
- if (self.mediaItems == nil) {
- [self fetchMediaItems];
- }
-
- for(VLCMediaLibraryMediaItem * const item in self.mediaItems) {
- mediaItemBlock(item);
- }
-}
-
- (int)setFavorite:(BOOL)favorite
{
const int res = setFavoriteForLibraryItem(vlc_ml_playlist_set_favorite, self.libraryID, favorite);
@@ -1552,7 +1588,15 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock
{
- mediaItemBlock(self);
+ [self enumerateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item, BOOL * const stop) {
+ mediaItemBlock(item);
+ }];
+}
+
+- (void)enumerateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem *item, BOOL *stop))mediaItemBlock
+{
+ BOOL stop = NO;
+ mediaItemBlock(self, &stop);
}
#pragma mark - preference setters / getters
@@ -1872,13 +1916,6 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
return self.episodes;
}
-- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock
-{
- for (VLCMediaLibraryMediaItem * const item in self.mediaItems) {
- mediaItemBlock(item);
- }
-}
-
@end
@implementation VLCMediaLibraryMovie
@@ -1914,13 +1951,6 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
return self.mediaItems.firstObject;
}
-- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock
-{
- for (VLCMediaLibraryMediaItem *item in self.mediaItems) {
- mediaItemBlock(item);
- }
-}
-
@end
@implementation VLCMediaLibraryEntryPoint
@@ -2017,8 +2047,19 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
- (void)iterateMediaItemsWithBlock:(nonnull void (^)(VLCMediaLibraryMediaItem * _Nonnull))mediaItemBlock
{
- for (VLCMediaLibraryMediaItem * const childItem in self.mediaItems) {
- mediaItemBlock(childItem);
+ [self enumerateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item, BOOL * const stop) {
+ mediaItemBlock(item);
+ }];
+}
+
+- (void)enumerateMediaItemsWithBlock:(nonnull void (^)(VLCMediaLibraryMediaItem * _Nonnull, BOOL * _Nonnull))mediaItemBlock
+{
+ for (VLCMediaLibraryMediaItem * const childItem in self.mediaItems) {
+ BOOL stop = NO;
+ mediaItemBlock(childItem, &stop);
+ if (stop) {
+ break;
+ }
}
}
=====================================
modules/gui/macosx/library/VLCLibraryImageCache.m
=====================================
@@ -275,43 +275,61 @@ const NSUInteger kVLCCompositeImageDefaultCompositedGridItemCount = 4;
![libraryItem isKindOfClass:VLCMediaLibraryMediaItem.class]) {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
- NSMutableArray<NSImage *> * const itemImages = [NSMutableArray array];
+ NSMutableSet<NSString *> * const seenMRLs = NSMutableSet.set;
+ NSMutableArray<VLCMediaLibraryMediaItem *> * const uniqueItems =
+ [NSMutableArray arrayWithCapacity:kVLCCompositeImageDefaultCompositedGridItemCount];
+
+ [libraryItem enumerateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item, BOOL * const stop) {
+ if (uniqueItems.count == (NSUInteger)kVLCCompositeImageDefaultCompositedGridItemCount) {
+ *stop = YES;
+ return;
+ }
+ NSString * const mrl = item.smallArtworkMRL;
+ if (mrl == nil || [seenMRLs containsObject:mrl]) {
+ return;
+ }
+ [seenMRLs addObject:mrl];
+ [uniqueItems addObject:item];
+ }];
+
+ if (uniqueItems.count == 0) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completionHandler(cache->_noArtImage);
+ });
+ return;
+ }
+
+ NSMutableArray<NSImage *> * const itemImages =
+ [NSMutableArray arrayWithCapacity:uniqueItems.count];
dispatch_group_t const group = dispatch_group_create();
- [libraryItem iterateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item) {
+ for (VLCMediaLibraryMediaItem * const item in uniqueItems) {
dispatch_group_enter(group);
[cache imageForLibraryItem:item withCompletion:^(const NSImage * thumbnail) {
NSImage * const mutableRef = (NSImage *)thumbnail;
- @synchronized (itemImages) {
- if (mutableRef && ![mutableRef isEqual:cache->_noArtImage]) {
+ if (mutableRef && ![mutableRef isEqual:cache->_noArtImage]) {
+ @synchronized (itemImages) {
[itemImages addObject:mutableRef];
}
}
dispatch_group_leave(group);
}];
- }];
-
- dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
-
- NSArray<NSImage *> *uniqueImages;
- @synchronized (itemImages) {
- uniqueImages = [NSOrderedSet orderedSetWithArray:itemImages].array;
}
- if (uniqueImages.count == 0) {
- dispatch_async(dispatch_get_main_queue(), ^{
+ dispatch_group_notify(group, dispatch_get_main_queue(), ^{
+ if (itemImages.count == 0) {
completionHandler(cache->_noArtImage);
- });
- return;
- }
+ return;
+ }
- const NSSize size = NSMakeSize(kVLCDesiredThumbnailWidth, kVLCDesiredThumbnailHeight);
- NSArray<NSValue *> * const frames =
- [NSImage framesForCompositeImageSquareGridWithImages:uniqueImages size:size gridItemCount:kVLCCompositeImageDefaultCompositedGridItemCount];
- NSImage * const compositeImage =
- [NSImage compositeImageWithImages:uniqueImages frames:frames size:size];
+ const NSSize size = NSMakeSize(kVLCDesiredThumbnailWidth, kVLCDesiredThumbnailHeight);
+ NSArray<NSValue *> * const frames =
+ [NSImage framesForCompositeImageSquareGridWithImages:itemImages
+ size:size
+ gridItemCount:kVLCCompositeImageDefaultCompositedGridItemCount];
+ NSImage * const compositeImage =
+ [NSImage compositeImageWithImages:itemImages frames:frames size:size];
- dispatch_async(dispatch_get_main_queue(), ^{
completionHandler(compositeImage);
});
});
=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAllAudioGroupsMediaLibraryItem.m
=====================================
@@ -66,10 +66,29 @@
- (void)iterateMediaItemsWithBlock:(nonnull void (^)(VLCMediaLibraryMediaItem * _Nonnull))mediaItemBlock
{
- // Iterate by album
+ [self enumerateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item, BOOL * const stop) {
+ mediaItemBlock(item);
+ }];
+}
+
+- (void)enumerateMediaItemsWithBlock:(nonnull void (^)(VLCMediaLibraryMediaItem * _Nonnull, BOOL * _Nonnull))mediaItemBlock
+{
NSArray<id<VLCMediaLibraryItemProtocol>> * const childItems = self.albums;
- for(id<VLCMediaLibraryItemProtocol> childItem in childItems) {
- [childItem iterateMediaItemsWithBlock:mediaItemBlock];
+ __block BOOL shouldStop = NO;
+ for (id<VLCMediaLibraryItemProtocol> const childItem in childItems) {
+ if (shouldStop) {
+ break;
+ }
+ [childItem enumerateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem * const item, BOOL * const stop) {
+ if (shouldStop) {
+ *stop = YES;
+ return;
+ }
+ mediaItemBlock(item, stop);
+ if (*stop) {
+ shouldStop = YES;
+ }
+ }];
}
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/5519a21dc1cc968963a2c74b03b2718c0a3216c5...43d24a4921a0d4ae9d2402eb9f7d939d96a555ef
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/5519a21dc1cc968963a2c74b03b2718c0a3216c5...43d24a4921a0d4ae9d2402eb9f7d939d96a555ef
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help
More information about the vlc-commits
mailing list