[vlc-commits] [Git][videolan/vlc][master] macosx: Keep media title suggestions in sync with cached items
Claudio Cambra (@claucambra)
gitlab at videolan.org
Sun Oct 4 07:26:47 UTC 2026
Claudio Cambra pushed to branch master at VideoLAN / VLC
Commits:
e77e49b5 by Claudio Cambra at 2026-10-04T07:11:47+00:00
macosx: Keep media title suggestions in sync with cached items
Track title references across audio and video caches to keep suggestions up to date after renames, deletions, and cache resets
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
1 changed file:
- modules/gui/macosx/library/VLCLibraryModel.m
Changes:
=====================================
modules/gui/macosx/library/VLCLibraryModel.m
=====================================
@@ -106,6 +106,7 @@ NSString * const VLCLibraryModelDiscoveryFailed = @"VLCLibraryModelDiscoveryFail
dispatch_queue_t _genreCacheModificationQueue;
dispatch_queue_t _groupCacheModificationQueue;
dispatch_queue_t _mediaTitlesCacheModificationQueue;
+ NSCountedSet<NSString *> *_mediaTitleCounts;
}
@property (readwrite) NSArray<VLCMediaLibraryFolderObserver *> *folderObservers;
@@ -131,7 +132,6 @@ NSString * const VLCLibraryModelDiscoveryFailed = @"VLCLibraryModelDiscoveryFail
- (void)resetCachedListOfShows;
- (void)resetCachedListOfGroups;
- (void)resetCachedListOfMonitoredFolders;
-- (void)resetCachedListOfMediaTitles;
- (void)mediaItemThumbnailGenerated:(VLCMediaLibraryMediaItem *)mediaItem;
- (void)handleMediaItemAddedEvent:(const vlc_ml_event_t * const)p_event;
- (void)handlePlaylistAddedEvent:(const vlc_ml_event_t * const)p_event;
@@ -332,6 +332,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
_genreCacheModificationQueue = dispatch_queue_create("genreCacheModificationQueue", DISPATCH_QUEUE_CONCURRENT);
_groupCacheModificationQueue = dispatch_queue_create("groupCacheModificationQueue", DISPATCH_QUEUE_CONCURRENT);
_mediaTitlesCacheModificationQueue = dispatch_queue_create("mediaTitlesCacheModificationQueue", DISPATCH_QUEUE_CONCURRENT);
+ _mediaTitleCounts = [NSCountedSet new];
_defaultNotificationCenter = NSNotificationCenter.defaultCenter;
[_defaultNotificationCenter addObserver:self
@@ -478,15 +479,19 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (void)setCachedAudioMedia:(NSArray *)cachedAudioMedia
{
+ NSArray * const media = [cachedAudioMedia copy];
dispatch_barrier_async(_mediaItemCacheModificationQueue, ^{
- self->_cachedAudioMedia = [cachedAudioMedia copy];
+ [self replaceMediaTitlesFromMedia:self->_cachedAudioMedia withMedia:media];
+ self->_cachedAudioMedia = media;
});
}
- (void)setCachedVideoMedia:(NSArray *)cachedVideoMedia
{
+ NSArray * const media = [cachedVideoMedia copy];
dispatch_barrier_async(_mediaItemCacheModificationQueue, ^{
- self->_cachedVideoMedia = [cachedVideoMedia copy];
+ [self replaceMediaTitlesFromMedia:self->_cachedVideoMedia withMedia:media];
+ self->_cachedVideoMedia = media;
});
}
@@ -603,7 +608,6 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
self.cachedAudioMedia = mediaArray;
[self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
[self.changeDelegate notifyChange:VLCLibraryModelAudioMediaListReset withObject:self];
- [self resetCachedListOfMediaTitles];
}];
});
});
@@ -794,7 +798,6 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
self.cachedVideoMedia = [mutableArray copy];
[self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
[self.changeDelegate notifyChange:VLCLibraryModelVideoMediaListReset withObject:self];
- [self resetCachedListOfMediaTitles];
}];
});
});
@@ -809,42 +812,80 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
return cache;
}
-- (void)resetCachedListOfMediaTitles
+- (void)replaceMediaTitlesFromMedia:(NSArray<VLCMediaLibraryMediaItem *> *)oldMedia
+ withMedia:(NSArray<VLCMediaLibraryMediaItem *> *)newMedia
{
- dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
- NSMutableSet<NSString *> * const titleSet = NSMutableSet.set;
-
- NSArray<VLCMediaLibraryMediaItem *> * const videos = self.listOfVideoMedia;
- for (VLCMediaLibraryMediaItem * const video in videos) {
- NSString * const title = video.displayString;
+ dispatch_barrier_async(_mediaTitlesCacheModificationQueue, ^{
+ for (VLCMediaLibraryMediaItem * const item in oldMedia) {
+ NSString * const title = item.displayString;
if (title) {
- [titleSet addObject:title];
+ [self->_mediaTitleCounts removeObject:title];
}
}
-
- NSArray<VLCMediaLibraryMediaItem *> * const audioMedia = self.listOfAudioMedia;
- for (VLCMediaLibraryMediaItem * const audio in audioMedia) {
- NSString * const title = audio.displayString;
+ for (VLCMediaLibraryMediaItem * const item in newMedia) {
+ NSString * const title = item.displayString;
if (title) {
- [titleSet addObject:title];
+ [self->_mediaTitleCounts addObject:title];
}
}
+ if (newMedia == nil && self->_mediaTitleCounts.count == 0) {
+ self->_cachedMediaTitles = nil;
+ } else if (newMedia != nil || self->_cachedMediaTitles != nil) {
+ self->_cachedMediaTitles = [self->_mediaTitleCounts.allObjects
+ sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
+ }
+ });
+}
- NSArray<NSString *> * const sortedTitles = [titleSet.allObjects sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
+- (void)replaceMediaTitle:(NSString *)oldTitle withTitle:(NSString *)newTitle
+{
+ if (oldTitle == newTitle || [oldTitle isEqualToString:newTitle]) {
+ return;
+ }
- dispatch_barrier_async(self->_mediaTitlesCacheModificationQueue, ^{
- self->_cachedMediaTitles = [sortedTitles copy];
- });
+ dispatch_barrier_async(_mediaTitlesCacheModificationQueue, ^{
+ BOOL removeTitle = NO;
+ BOOL insertTitle = NO;
+ if (oldTitle && [self->_mediaTitleCounts countForObject:oldTitle] > 0) {
+ [self->_mediaTitleCounts removeObject:oldTitle];
+ removeTitle = [self->_mediaTitleCounts countForObject:oldTitle] == 0;
+ }
+ if (newTitle) {
+ insertTitle = [self->_mediaTitleCounts countForObject:newTitle] == 0;
+ [self->_mediaTitleCounts addObject:newTitle];
+ }
+ if (self->_cachedMediaTitles == nil || (!removeTitle && !insertTitle)) {
+ return;
+ }
+
+ NSMutableArray<NSString *> * const titles = self->_cachedMediaTitles.mutableCopy;
+ if (removeTitle) {
+ [titles removeObject:oldTitle];
+ }
+ if (insertTitle) {
+ const NSUInteger index =
+ [titles indexOfObject:newTitle
+ inSortedRange:NSMakeRange(0, titles.count)
+ options:NSBinarySearchingInsertionIndex
+ usingComparator:^NSComparisonResult(NSString *left, NSString *right) {
+ return [left localizedCaseInsensitiveCompare:right];
+ }];
+ [titles insertObject:newTitle atIndex:index];
+ }
+ self->_cachedMediaTitles = titles.copy;
});
}
- (NSArray<NSString *> *)listOfMediaTitles
{
- NSArray<NSString *> * const cache = self.cachedMediaTitles;
- if (cache == nil) {
- [self resetCachedListOfMediaTitles];
+ // Source setters maintain the counts; only a title lookup loads missing sources.
+ if (self.cachedAudioMedia == nil) {
+ [self resetCachedListOfAudioMedia];
}
- return cache;
+ if (self.cachedVideoMedia == nil) {
+ [self resetCachedListOfVideoMedia];
+ }
+ return self.cachedMediaTitles;
}
- (void)getListOfRecentMediaOfType:(vlc_ml_media_type_t)type
@@ -1305,7 +1346,6 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
self.cachedArtists = nil;
self.cachedGenres = nil;
self.cachedListOfGroups = nil;
- self.cachedMediaTitles = nil;
// Barrier sentinels complete after the setter writes on each queue.
for (NSUInteger index = 0; index < cacheQueueCount; index++) {
@@ -1314,8 +1354,13 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
});
}
- dispatch_group_notify(cacheDropGroup, dispatch_get_main_queue(), ^{
- [self.changeDelegate notifyChange:VLCLibraryModelAllCachesDropped withObject:self];
+ dispatch_group_notify(cacheDropGroup, _mediaTitlesCacheModificationQueue, ^{
+ // Source setters have now submitted their title updates. Queue the final
+ // clear after those updates so none can restore the dropped title cache.
+ self.cachedMediaTitles = nil;
+ [self performAfterCacheWritesOnQueue:self->_mediaTitlesCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelAllCachesDropped withObject:self];
+ }];
});
}
@@ -1366,7 +1411,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
showIndex == NSNotFound ? nil : cachedShows.mutableCopy;
action(videoMutable, videoIndex, recentsMutable, recentsIndex, showsMutable, showIndex, episodeIndex);
- self.cachedVideoMedia = videoMutable.copy;
+ // Item handlers adjust title counts individually inside this barrier.
+ self->_cachedVideoMedia = videoMutable.copy;
self.cachedRecentMedia = recentsMutable.copy;
if (showsMutable)
self.cachedListOfShows = showsMutable.copy;
@@ -1386,7 +1432,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
NSMutableArray<VLCMediaLibraryMediaItem *> * const audioMutable = cachedAudios.mutableCopy;
action(audioMutable, audioIndex, recentAudiosMutable, recentAudiosIndex, nil, NSNotFound, NSNotFound);
- self.cachedAudioMedia = audioMutable.copy;
+ self->_cachedAudioMedia = audioMutable.copy;
self.cachedRecentAudioMedia = recentAudiosMutable.copy;
return;
}
@@ -1424,6 +1470,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
// Notify what happened
if (cachedMediaIndex != NSNotFound) {
+ [self replaceMediaTitle:((VLCMediaLibraryMediaItem *)cachedMediaArray[cachedMediaIndex]).displayString
+ withTitle:mediaItem.displayString];
[cachedMediaArray replaceObjectAtIndex:cachedMediaIndex withObject:mediaItem];
}
@@ -1499,6 +1547,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
? cachedMediaArray[cachedMediaIndex] : recentMediaArray[recentMediaIndex];
// Notify what happened
if (cachedMediaIndex != NSNotFound) {
+ [self replaceMediaTitle:mediaItem.displayString withTitle:nil];
[cachedMediaArray removeObjectAtIndex:cachedMediaIndex];
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/e77e49b5dff7484dbf70cd1540a6a568e1890280
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/e77e49b5dff7484dbf70cd1540a6a568e1890280
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