[vlc-commits] [Git][videolan/vlc][master] 45 commits: macosx: Give the notification name for thumbnails generated for media items a more accurate name

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Tue Mar 28 18:26:12 UTC 2023



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
d1986e60 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Give the notification name for thumbnails generated for media items a more accurate name

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

- - - - -
e7e9b0f9 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Only update video collection views if received notification type calls for it

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

- - - - -
9e0b2e93 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Add performActionOnMediaItemFromCache method in VLCLibraryModel

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

- - - - -
723353c7 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Handle media deleted events in media library model granularly

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

- - - - -
b0295a18 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Handle media library update/reset events more granularly

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

- - - - -
97d9718f by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Respond to both relevant library model notifications in VLCLibraryVideoViewController

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

- - - - -
aa123ee7 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Add reloadData method to VLCLibraryVideoCollectionViewContainerViewDataSource with completion handler

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

- - - - -
cb269c62 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Add method to reload data by index in VLCLibraryVideoCollectionViewContainerViewDataSource

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

- - - - -
886ec1cb by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Handle granular VLCLibraryModelVideoMediaItemUpdated in VLCLibraryVideoCollectionViewContainerViewDataSource

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

- - - - -
7b828cb1 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Do not return an error from performActionOnMediaItemFromCache if the media item was found in the recent media

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

- - - - -
1a64b6b0 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Extract the acquisition of model index from notification user info into own method in VLCLibraryVideoCollectionViewContainerViewDataSource

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

- - - - -
e7d741c6 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Update the recents collection view in video view when received notification of change

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

- - - - -
f2a86c09 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Add deleteDataForIndex method to VLCLibraryVideoCollectionViewContainerViewDataSource

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

- - - - -
fd8d52ec by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Properly handle media item deletion notification in general videos and recents in VLCLibraryVideoCollectionViewContainerViewDataSource

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

- - - - -
2c187264 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Move modelIndexFromModelItemNotification to VLCLibraryModel as class method

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

- - - - -
176a5052 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Also handle VLCLibraryModelAudioMediaItemDeleted when checking for view to present in VLCLibraryAudioViewController

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

- - - - -
a0a73abc by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Add reloadDataWithCompletionHandler to VLCLibraryVideoTableViewDataSource

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

- - - - -
dc67bd1c by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Add indexed reload data methods in VLCLibraryVideoTableViewDataSource

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

- - - - -
b80a6e79 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Handle reset of recents and video list in library model selectively in VLCLibraryVideoTableViewDataSource

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

- - - - -
51baa1d3 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Handle video and recents library item notifications in VLCLibraryVideoTableViewDataSource

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

- - - - -
c237e7f4 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Implement reloadDataWithCompletion in VLCLibraryAudioDataSource

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

- - - - -
3cd9705e by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Remove premature optimisation in libraryModelUpdated of VLCLibraryAudioDataSource

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

- - - - -
e776f567 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Move collectionToDisplay logic in libraryModelUpdated to separate method

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

- - - - -
85a2c8df by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Set the displayed collection of the VLCLibraryAudioDataSource in reloadDataWithCompletion

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

- - - - -
f6b9e699 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Add reloadDataForMediaLibraryItem method to VLCLibraryAudioDataSource

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

- - - - -
3e7230f5 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Add deleteDataForMediaLibraryItem to VLCLibraryAudioDataSource

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

- - - - -
328352c9 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Deduplicate media item index search in reload and delete methods of VLCLibraryAudioDataSource

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

- - - - -
5f47c13b by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Constify new library model update methods

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

- - - - -
a6c2a08f by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Handle VLCLibraryModelAudioMediaItemUpdated in VLCLibraryAudioDataSource

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

- - - - -
43609a2b by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Add convenience resetCachedMediaItemLists method in VLCLibraryModel

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

- - - - -
34481c3a by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Ensure cached media item lists are reset even if we received media item update or delete event

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

- - - - -
a8e256bb by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Make sending off a reset notification in reset method of VLCLibraryModel optional

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

- - - - -
d7876102 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Check if media item exists first before trying to find where it is in cached array

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

- - - - -
1b621064 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Add possibility to run media item resetters in VLCLibraryModel with completion handlers

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

- - - - -
e240d90f by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Add completionHandler to VLCLibraryModel resetCachedMediaItemListsWithNotification

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

- - - - -
b7e5689f by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Ensure we are only doing actions on cache items in VLCLibraryModel once the cache jobs have finished

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

- - - - -
9c7ef35b by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Remove ineffective and bug causing dispatch_asyncs in VLCLibraryModel

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

- - - - -
244a5a20 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Change access for cache arrays in VLCLibraryModel to go through guarded atomic property

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

- - - - -
95862c5d by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Move fetch of items from library model in video container view data source to background thread

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

- - - - -
04bc3fbe by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Reload specific items in VLCLibraryVideoCollectionViewContainerViewDataSource not by VLCLibraryModel index

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

- - - - -
a53bdc73 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Use VLCMediaLibraryMediaItems to update the VLCLibraryVideoTableViewDataSource

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

- - - - -
7072861c by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Update container view data source on non-main dispatch queue

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

- - - - -
01036b28 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Do not reset entire collection array in audio data source when updating or deleting

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

- - - - -
bb971898 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Do not do unnecessary cache resets when updating or deleting, rather modify items directly

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

- - - - -
4c6222e6 by Claudio Cambra at 2023-03-28T18:11:29+00:00
macosx: Ensure cache modification does not occur concurrently

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

- - - - -


10 changed files:

- modules/gui/macosx/library/VLCLibraryCollectionViewItem.m
- modules/gui/macosx/library/VLCLibraryModel.h
- modules/gui/macosx/library/VLCLibraryModel.m
- modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.m
- modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.m
- modules/gui/macosx/library/video-library/VLCLibraryVideoCollectionViewContainerViewDataSource.m
- modules/gui/macosx/library/video-library/VLCLibraryVideoGroupDescriptor.h
- modules/gui/macosx/library/video-library/VLCLibraryVideoGroupDescriptor.m
- modules/gui/macosx/library/video-library/VLCLibraryVideoTableViewDataSource.m
- modules/gui/macosx/library/video-library/VLCLibraryVideoViewController.m


Changes:

=====================================
modules/gui/macosx/library/VLCLibraryCollectionViewItem.m
=====================================
@@ -92,8 +92,8 @@ const CGFloat VLCLibraryCollectionViewItemMaximumDisplayedProgress = 0.95;
     if (self) {
         NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
         [notificationCenter addObserver:self
-                               selector:@selector(mediaItemUpdated:)
-                                   name:VLCLibraryModelMediaItemUpdated
+                               selector:@selector(mediaItemThumbnailGenerated:)
+                                   name:VLCLibraryModelMediaItemThumbnailGenerated
                                  object:nil];
         [notificationCenter addObserver:self
                                selector:@selector(updateFontBasedOnSetting:)
@@ -211,7 +211,7 @@ const CGFloat VLCLibraryCollectionViewItemMaximumDisplayedProgress = 0.95;
     _highlightBox.hidden = !selected;
 }
 
-- (void)mediaItemUpdated:(NSNotification *)aNotification
+- (void)mediaItemThumbnailGenerated:(NSNotification *)aNotification
 {
     VLCMediaLibraryMediaItem *updatedMediaItem = aNotification.object;
     if (updatedMediaItem == nil || _representedItem == nil || ![_representedItem isKindOfClass:[VLCMediaLibraryMediaItem class]]) {


=====================================
modules/gui/macosx/library/VLCLibraryModel.h
=====================================
@@ -32,17 +32,28 @@ NS_ASSUME_NONNULL_BEGIN
 @class VLCMediaLibraryGenre;
 @class VLCMediaLibraryEntryPoint;
 
-extern NSString *VLCLibraryModelAudioMediaListUpdated;
 extern NSString *VLCLibraryModelArtistListUpdated;
 extern NSString *VLCLibraryModelAlbumListUpdated;
 extern NSString *VLCLibraryModelGenreListUpdated;
-extern NSString *VLCLibraryModelVideoMediaListUpdated;
-extern NSString *VLCLibraryModelRecentMediaListUpdated;
 extern NSString *VLCLibraryModelListOfMonitoredFoldersUpdated;
-extern NSString *VLCLibraryModelMediaItemUpdated;
+extern NSString *VLCLibraryModelMediaItemThumbnailGenerated;
+
+extern NSString *VLCLibraryModelAudioMediaListReset;
+extern NSString *VLCLibraryModelVideoMediaListReset;
+extern NSString *VLCLibraryModelRecentsMediaListReset;
+
+extern NSString *VLCLibraryModelAudioMediaItemDeleted;
+extern NSString *VLCLibraryModelVideoMediaItemDeleted;
+extern NSString *VLCLibraryModelRecentsMediaItemDeleted;
+
+extern NSString *VLCLibraryModelAudioMediaItemUpdated;
+extern NSString *VLCLibraryModelVideoMediaItemUpdated;
+extern NSString *VLCLibraryModelRecentsMediaItemUpdated;
 
 @interface VLCLibraryModel : NSObject
 
++ (NSUInteger)modelIndexFromModelItemNotification:(NSNotification * const)aNotification;
+
 - (instancetype)initWithLibrary:(vlc_medialibrary_t *)library;
 
 @property (readonly) size_t numberOfAudioMedia;


=====================================
modules/gui/macosx/library/VLCLibraryModel.m
=====================================
@@ -26,14 +26,23 @@
 #import "library/VLCLibraryDataTypes.h"
 #import "extensions/NSString+Helpers.h"
 
-NSString *VLCLibraryModelAudioMediaListUpdated = @"VLCLibraryModelAudioMediaListUpdated";
 NSString *VLCLibraryModelArtistListUpdated = @"VLCLibraryModelArtistListUpdated";
 NSString *VLCLibraryModelAlbumListUpdated = @"VLCLibraryModelAlbumListUpdated";
 NSString *VLCLibraryModelGenreListUpdated = @"VLCLibraryModelGenreListUpdated";
-NSString *VLCLibraryModelVideoMediaListUpdated = @"VLCLibraryModelVideoMediaListUpdated";
-NSString *VLCLibraryModelRecentMediaListUpdated = @"VLCLibraryModelRecentMediaListUpdated";
 NSString *VLCLibraryModelListOfMonitoredFoldersUpdated = @"VLCLibraryModelListOfMonitoredFoldersUpdated";
-NSString *VLCLibraryModelMediaItemUpdated = @"VLCLibraryModelMediaItemUpdated";
+NSString *VLCLibraryModelMediaItemThumbnailGenerated = @"VLCLibraryModelMediaItemThumbnailGenerated";
+
+NSString *VLCLibraryModelAudioMediaListReset = @"VLCLibraryModelAudioMediaListReset";
+NSString *VLCLibraryModelVideoMediaListReset = @"VLCLibraryModelVideoMediaListReset";
+NSString *VLCLibraryModelRecentsMediaListReset = @"VLCLibraryModelRecentsMediaListReset";
+
+NSString *VLCLibraryModelAudioMediaItemDeleted = @"VLCLibraryModelAudioMediaItemDeleted";
+NSString *VLCLibraryModelVideoMediaItemDeleted = @"VLCLibraryModelVideoMediaItemDeleted";
+NSString *VLCLibraryModelRecentsMediaItemDeleted = @"VLCLibraryModelRecentsMediaItemDeleted";
+
+NSString *VLCLibraryModelAudioMediaItemUpdated = @"VLCLibraryModelAudioMediaItemUpdated";
+NSString *VLCLibraryModelVideoMediaItemUpdated = @"VLCLibraryModelVideoMediaItemUpdated";
+NSString *VLCLibraryModelRecentsMediaItemUpdated = @"VLCLibraryModelRecentsMediaItemUpdated";
 
 @interface VLCLibraryModel ()
 {
@@ -55,16 +64,26 @@ NSString *VLCLibraryModelMediaItemUpdated = @"VLCLibraryModelMediaItemUpdated";
     
     size_t _initialVideoCount;
     size_t _initialAudioCount;
+
+    dispatch_queue_t _mediaItemCacheModificationQueue;
 }
 
-- (void)updateCachedListOfAudioMedia;
-- (void)updateCachedListOfVideoMedia;
-- (void)updateCachedListOfRecentMedia;
-- (void)updateCachedListOfArtists;
-- (void)updateCachedListOfAlbums;
-- (void)updateCachedListOfGenres;
-- (void)updateCachedListOfMonitoredFolders;
-- (void)mediaItemWasUpdated:(VLCMediaLibraryMediaItem *)mediaItem;
+ at property (readwrite, atomic) NSArray *cachedAudioMedia;
+ at property (readwrite, atomic) NSArray *cachedArtists;
+ at property (readwrite, atomic) NSArray *cachedAlbums;
+ at property (readwrite, atomic) NSArray *cachedGenres;
+ at property (readwrite, atomic) NSArray *cachedVideoMedia;
+ at property (readwrite, atomic) NSArray *cachedRecentMedia;
+ at property (readwrite, atomic) NSArray *cachedListOfMonitoredFolders;
+
+- (void)resetCachedMediaItemLists;
+- (void)resetCachedListOfArtists;
+- (void)resetCachedListOfAlbums;
+- (void)resetCachedListOfGenres;
+- (void)resetCachedListOfMonitoredFolders;
+- (void)mediaItemThumbnailGenerated:(VLCMediaLibraryMediaItem *)mediaItem;
+- (void)handleMediaItemDeletionEvent:(const vlc_ml_event_t * const)p_event;
+- (void)handleMediaItemUpdateEvent:(const vlc_ml_event_t * const)p_event;
 
 @end
 
@@ -73,15 +92,23 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     switch(p_event->i_type)
     {
         case VLC_ML_EVENT_MEDIA_ADDED:
+        {
+            VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
+            [libraryModel resetCachedMediaItemLists];
+            break;
+        }
         case VLC_ML_EVENT_MEDIA_UPDATED:
+        {
+            VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
+            [libraryModel handleMediaItemUpdateEvent:p_event];
+            break;
+        }
         case VLC_ML_EVENT_MEDIA_DELETED:
-            dispatch_async(dispatch_get_main_queue(), ^{
-                VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
-                [libraryModel updateCachedListOfRecentMedia];
-                [libraryModel updateCachedListOfAudioMedia];
-                [libraryModel updateCachedListOfVideoMedia];
-            });
+        {
+            VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
+            [libraryModel handleMediaItemDeletionEvent:p_event];
             break;
+        }
         case VLC_ML_EVENT_MEDIA_THUMBNAIL_GENERATED:
             if (p_event->media_thumbnail_generated.b_success) {
                 VLCMediaLibraryMediaItem *mediaItem = [[VLCMediaLibraryMediaItem alloc] initWithMediaItem:(struct vlc_ml_media_t *)p_event->media_thumbnail_generated.p_media];
@@ -90,7 +117,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
                 }
                 dispatch_async(dispatch_get_main_queue(), ^{
                     VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
-                    [libraryModel mediaItemWasUpdated:mediaItem];
+                    [libraryModel mediaItemThumbnailGenerated:mediaItem];
                 });
             }
             break;
@@ -98,40 +125,33 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         case VLC_ML_EVENT_ARTIST_UPDATED:
         case VLC_ML_EVENT_ARTIST_DELETED:
         {
-            dispatch_async(dispatch_get_main_queue(), ^{
-                VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
-                [libraryModel updateCachedListOfArtists];
-            });
+            VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
+            [libraryModel resetCachedListOfArtists];
             break;
         }
         case VLC_ML_EVENT_ALBUM_ADDED:
         case VLC_ML_EVENT_ALBUM_UPDATED:
         case VLC_ML_EVENT_ALBUM_DELETED:
         {
-            dispatch_async(dispatch_get_main_queue(), ^{
-                VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
-                [libraryModel updateCachedListOfAlbums];
-            });
+            VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
+            [libraryModel resetCachedListOfAlbums];
             break;
         }
         case VLC_ML_EVENT_GENRE_ADDED:
         case VLC_ML_EVENT_GENRE_UPDATED:
         case VLC_ML_EVENT_GENRE_DELETED:
         {
-            dispatch_async(dispatch_get_main_queue(), ^{
-                VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
-                [libraryModel updateCachedListOfGenres];
-            });
+            VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
+            [libraryModel resetCachedListOfGenres];
             break;
         }
         case VLC_ML_EVENT_FOLDER_ADDED:
         case VLC_ML_EVENT_FOLDER_UPDATED:
         case VLC_ML_EVENT_FOLDER_DELETED:
         {
-            dispatch_async(dispatch_get_main_queue(), ^{
-                VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
-                [libraryModel updateCachedListOfMonitoredFolders];
-            });
+            VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
+            [libraryModel resetCachedListOfMonitoredFolders];
+            break;
         }
         default:
             break;
@@ -140,6 +160,18 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 
 @implementation VLCLibraryModel
 
++ (NSUInteger)modelIndexFromModelItemNotification:(NSNotification * const)aNotification
+{
+    NSParameterAssert(aNotification);
+    NSDictionary * const notificationUserInfo = aNotification.userInfo;
+    NSAssert(notificationUserInfo != nil, @"Video item-related notification should carry valid user info");
+
+    NSNumber * const modelIndexNumber = (NSNumber * const)[notificationUserInfo objectForKey:@"index"];
+    NSAssert(modelIndexNumber != nil, @"Video item notification user info should carry index for updated item");
+
+    return modelIndexNumber.longLongValue;
+}
+
 - (instancetype)initWithLibrary:(vlc_medialibrary_t *)library
 {
     self = [super init];
@@ -149,15 +181,18 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         _filterString = @"";
         _p_mediaLibrary = library;
         _p_eventCallback = vlc_ml_event_register_callback(_p_mediaLibrary, libraryCallback, (__bridge void *)self);
+
+        _mediaItemCacheModificationQueue = dispatch_queue_create("mediaItemCacheModificationQueue", 0);
+
         _defaultNotificationCenter = [NSNotificationCenter defaultCenter];
         [_defaultNotificationCenter addObserver:self
                                        selector:@selector(applicationWillTerminate:)
                                            name:NSApplicationWillTerminateNotification
                                          object:nil];
-        
+
         dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
             const vlc_ml_query_params_t queryParameters = {};
-            
+
             // Preload video and audio count for gui
             self->_initialVideoCount = vlc_ml_count_video_media(self->_p_mediaLibrary, &queryParameters);
             self->_initialAudioCount = vlc_ml_count_audio_media(self->_p_mediaLibrary, &queryParameters);
@@ -178,18 +213,16 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     [_defaultNotificationCenter removeObserver:self];
 }
 
-- (void)mediaItemWasUpdated:(VLCMediaLibraryMediaItem *)mediaItem
+- (void)mediaItemThumbnailGenerated:(VLCMediaLibraryMediaItem *)mediaItem
 {
-    [_defaultNotificationCenter postNotificationName:VLCLibraryModelMediaItemUpdated object:mediaItem];
+    [_defaultNotificationCenter postNotificationName:VLCLibraryModelMediaItemThumbnailGenerated object:mediaItem];
 }
 
 - (size_t)numberOfAudioMedia
 {
     if (!_cachedAudioMedia) {
-        dispatch_async(dispatch_get_main_queue(), ^{
-            [self updateCachedListOfAudioMedia];
-        });
-        
+        [self resetCachedListOfAudioMedia];
+
         // Return initial count here, otherwise it will return 0 on the first time
         return _initialAudioCount;
     }
@@ -204,7 +237,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     return queryParams;
 }
 
-- (void)updateCachedListOfAudioMedia
+- (void)resetCachedListOfAudioMedia
 {
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
         const vlc_ml_query_params_t queryParams = [self queryParams];
@@ -222,8 +255,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         }
         vlc_ml_media_list_release(p_media_list);
         dispatch_async(dispatch_get_main_queue(), ^{
-            self->_cachedAudioMedia = [mutableArray copy];
-            [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaListUpdated object:self];
+            self.cachedAudioMedia = [mutableArray copy];
+            [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaListReset object:self];
         });
     });
 }
@@ -231,7 +264,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 - (NSArray<VLCMediaLibraryMediaItem *> *)listOfAudioMedia
 {
     if (!_cachedAudioMedia) {
-        [self updateCachedListOfAudioMedia];
+        [self resetCachedListOfAudioMedia];
     }
     return _cachedAudioMedia;
 }
@@ -239,12 +272,12 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 - (size_t)numberOfArtists
 {
     if (!_cachedArtists) {
-        [self updateCachedListOfArtists];
+        [self resetCachedListOfArtists];
     }
     return _cachedArtists.count;
 }
 
-- (void)updateCachedListOfArtists
+- (void)resetCachedListOfArtists
 {
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
         const vlc_ml_query_params_t queryParams = [self queryParams];
@@ -258,7 +291,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         }
         vlc_ml_artist_list_release(p_artist_list);
         dispatch_async(dispatch_get_main_queue(), ^{
-            self->_cachedArtists = [mutableArray copy];
+            self.cachedArtists = [mutableArray copy];
             [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelArtistListUpdated object:self];
         });
     });
@@ -267,7 +300,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 - (NSArray<VLCMediaLibraryArtist *> *)listOfArtists
 {
     if (!_cachedArtists) {
-        [self updateCachedListOfArtists];
+        [self resetCachedListOfArtists];
     }
     return _cachedArtists;
 }
@@ -275,12 +308,12 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 - (size_t)numberOfAlbums
 {
     if (!_cachedAlbums) {
-        [self updateCachedListOfAlbums];
+        [self resetCachedListOfAlbums];
     }
     return _cachedAlbums.count;
 }
 
-- (void)updateCachedListOfAlbums
+- (void)resetCachedListOfAlbums
 {
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
         const vlc_ml_query_params_t queryParams = [self queryParams];
@@ -292,7 +325,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         }
         vlc_ml_album_list_release(p_album_list);
         dispatch_async(dispatch_get_main_queue(), ^{
-            self->_cachedAlbums = [mutableArray copy];
+            self.cachedAlbums = [mutableArray copy];
             [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelAlbumListUpdated object:self];
         });
     });
@@ -301,7 +334,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 - (NSArray<VLCMediaLibraryAlbum *> *)listOfAlbums
 {
     if (!_cachedAlbums) {
-        [self updateCachedListOfAlbums];
+        [self resetCachedListOfAlbums];
     }
     return _cachedAlbums;
 }
@@ -309,12 +342,12 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 - (size_t)numberOfGenres
 {
     if (!_cachedGenres) {
-        [self updateCachedListOfGenres];
+        [self resetCachedListOfGenres];
     }
     return _cachedGenres.count;
 }
 
-- (void)updateCachedListOfGenres
+- (void)resetCachedListOfGenres
 {
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
         const vlc_ml_query_params_t queryParams = [self queryParams];
@@ -326,7 +359,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         }
         vlc_ml_genre_list_release(p_genre_list);
         dispatch_async(dispatch_get_main_queue(), ^{
-            self->_cachedGenres = [mutableArray copy];
+            self.cachedGenres = [mutableArray copy];
             [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelGenreListUpdated object:self];
         });
     });
@@ -335,7 +368,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 - (NSArray<VLCMediaLibraryMediaItem *> *)listOfGenres
 {
     if (!_cachedGenres) {
-        [self updateCachedListOfGenres];
+        [self resetCachedListOfGenres];
     }
     return _cachedGenres;
 }
@@ -343,17 +376,15 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 - (size_t)numberOfVideoMedia
 {
     if (!_cachedVideoMedia) {
-        dispatch_async(dispatch_get_main_queue(), ^{
-            [self updateCachedListOfVideoMedia];
-        });
-        
+        [self resetCachedListOfVideoMedia];
+
         // Return initial count here, otherwise it will return 0 on the first time
         return _initialVideoCount;
     }
     return _cachedVideoMedia.count;
 }
 
-- (void)updateCachedListOfVideoMedia
+- (void)resetCachedListOfVideoMedia
 {
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
         const vlc_ml_query_params_t queryParameters = [self queryParams];
@@ -370,8 +401,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         }
         vlc_ml_media_list_release(p_media_list);
         dispatch_async(dispatch_get_main_queue(), ^{
-            self->_cachedVideoMedia = [mutableArray copy];
-            [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaListUpdated object:self];
+            self.cachedVideoMedia = [mutableArray copy];
+            [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaListReset object:self];
         });
     });
 }
@@ -379,14 +410,12 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 - (NSArray<VLCMediaLibraryMediaItem *> *)listOfVideoMedia
 {
     if (!_cachedVideoMedia) {
-        dispatch_async(dispatch_get_main_queue(), ^{
-            [self updateCachedListOfVideoMedia];
-        });
+        [self resetCachedListOfVideoMedia];
     }
     return _cachedVideoMedia;
 }
 
-- (void)updateCachedListOfRecentMedia
+- (void)resetCachedListOfRecentMedia
 {
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
         const vlc_ml_query_params_t queryParameters = { .i_nbResults = 20 };
@@ -405,8 +434,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         }
         vlc_ml_media_list_release(p_media_list);
         dispatch_async(dispatch_get_main_queue(), ^{
-            self->_cachedRecentMedia = [mutableArray copy];
-            [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelRecentMediaListUpdated object:self];
+            self.cachedRecentMedia = [mutableArray copy];
+            [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelRecentsMediaListReset object:self];
         });
     });
 }
@@ -415,7 +444,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 {
     if (!_cachedRecentMedia) {
         dispatch_async(dispatch_get_main_queue(), ^{
-            [self updateCachedListOfRecentMedia];
+            [self resetCachedListOfRecentMedia];
         });
     }
     return _cachedRecentMedia.count;
@@ -425,13 +454,20 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 {
     if (!_cachedRecentMedia) {
         dispatch_async(dispatch_get_main_queue(), ^{
-            [self updateCachedListOfRecentMedia];
+            [self resetCachedListOfRecentMedia];
         });
     }
     return _cachedRecentMedia;
 }
 
-- (void)updateCachedListOfMonitoredFolders
+- (void)resetCachedMediaItemLists
+{
+    [self resetCachedListOfRecentMedia];
+    [self resetCachedListOfAudioMedia];
+    [self resetCachedListOfVideoMedia];
+}
+
+- (void)resetCachedListOfMonitoredFolders
 {
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
         vlc_ml_folder_list_t *pp_entrypoints = vlc_ml_list_entry_points(self->_p_mediaLibrary, NULL);
@@ -451,7 +487,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         vlc_ml_folder_list_release(pp_entrypoints);
 
         dispatch_async(dispatch_get_main_queue(), ^{
-            self->_cachedListOfMonitoredFolders = [mutableArray copy];
+            self.cachedListOfMonitoredFolders = [mutableArray copy];
             [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelListOfMonitoredFoldersUpdated object:self];
         });
     });
@@ -460,9 +496,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 - (NSArray<VLCMediaLibraryEntryPoint *> *)listOfMonitoredFolders
 {
     if(!_cachedListOfMonitoredFolders) {
-        dispatch_async(dispatch_get_main_queue(), ^{
-            [self updateCachedListOfMonitoredFolders];
-        });
+        [self resetCachedListOfMonitoredFolders];
     }
 
     return _cachedListOfMonitoredFolders;
@@ -513,8 +547,125 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     _cachedArtists = nil;
     _cachedAudioMedia = nil;
 
-    [_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaListUpdated object:self];
-    [_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaListUpdated object:self];
+    [_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaListReset object:self];
+    [_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaListReset object:self];
+}
+
+- (void)performActionOnMediaItemInCache:(const int64_t)libraryId action:(void (^)(const NSMutableArray*, const NSUInteger, const NSMutableArray*, const NSUInteger))action
+{
+    dispatch_async(_mediaItemCacheModificationQueue, ^{
+        BOOL (^idCheckBlock)(VLCMediaLibraryMediaItem * const, const NSUInteger, BOOL * const) = ^BOOL(VLCMediaLibraryMediaItem * const mediaItem, const NSUInteger idx, BOOL * const stop) {
+            NSAssert(mediaItem != nil, @"Cache list should not contain nil media items");
+            return mediaItem.libraryID == libraryId;
+        };
+
+        // Recents can contain media items the other two do
+        NSMutableArray * const recentsMutable = [self.cachedRecentMedia mutableCopy];
+        const NSUInteger recentsIndex = [recentsMutable indexOfObjectPassingTest:idCheckBlock];
+        BOOL isInRecents = recentsIndex != NSNotFound;
+
+        NSMutableArray * const videoMutable = [self.cachedVideoMedia mutableCopy];
+        const NSUInteger videoIndex = [videoMutable indexOfObjectPassingTest:idCheckBlock];
+        if (videoIndex != NSNotFound) {
+            dispatch_sync(dispatch_get_main_queue(), ^{
+                action(videoMutable, videoIndex, recentsMutable, recentsIndex);
+                self.cachedVideoMedia = [videoMutable copy];
+                self.cachedRecentMedia = [recentsMutable copy];
+            });
+            return;
+        }
+
+        NSMutableArray * const audioMutable = [self.cachedAudioMedia mutableCopy];
+        const NSUInteger audioIndex = [self.cachedAudioMedia indexOfObjectPassingTest:idCheckBlock];
+        if (audioIndex != NSNotFound) {
+            dispatch_sync(dispatch_get_main_queue(), ^{
+                action(audioMutable, audioIndex, recentsMutable, recentsIndex);
+                self.cachedAudioMedia = [audioMutable copy];
+                self.cachedRecentMedia = [recentsMutable copy];
+            });
+            return;
+        }
+
+        action(nil, NSNotFound, nil, NSNotFound);
+    });
+}
+
+- (void)handleMediaItemUpdateEvent:(const vlc_ml_event_t * const)p_event
+{
+    NSParameterAssert(p_event != NULL);
+
+    const int64_t itemId = p_event->modification.i_entity_id;
+
+    VLCMediaLibraryMediaItem * const mediaItem = [VLCMediaLibraryMediaItem mediaItemForLibraryID:itemId];
+    if (mediaItem == nil) {
+        NSLog(@"Could not find a library media item with this ID. Can't handle update.");
+        return;
+    }
+
+    [self performActionOnMediaItemInCache:itemId action:^(NSMutableArray * const cachedMediaArray, const NSUInteger cachedMediaIndex, NSMutableArray * const recentMediaArray, const NSUInteger recentMediaIndex) {
+
+        if (cachedMediaArray == nil || cachedMediaIndex == NSNotFound) {
+            NSLog(@"Could not handle update for media library item with id %lld in model", itemId);
+            return;
+        }
+
+        // Notify what happened
+        [cachedMediaArray replaceObjectAtIndex:cachedMediaIndex withObject:mediaItem];
+
+        if (recentMediaArray != nil && recentMediaIndex != NSNotFound) {
+            [cachedMediaArray replaceObjectAtIndex:recentMediaIndex withObject:mediaItem];
+            [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelRecentsMediaItemUpdated object:mediaItem];
+        }
+
+        switch (mediaItem.mediaType) {
+            case VLC_ML_MEDIA_TYPE_VIDEO:
+                [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaItemUpdated object:mediaItem];
+                break;
+            case VLC_ML_MEDIA_TYPE_AUDIO:
+                [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaItemUpdated object:mediaItem];
+                break;
+            case VLC_ML_MEDIA_TYPE_UNKNOWN:
+                NSLog(@"Unknown type of media type encountered, don't know what to do in update");
+                break;
+        }
+    }];
+}
+
+- (void)handleMediaItemDeletionEvent:(const vlc_ml_event_t * const)p_event
+{
+    NSParameterAssert(p_event != NULL);
+
+    const int64_t itemId = p_event->modification.i_entity_id;
+    NSLog(@"Deleting %lli", itemId);
+
+    [self performActionOnMediaItemInCache:itemId action:^(NSMutableArray * const cachedMediaArray, const NSUInteger cachedMediaIndex, NSMutableArray * const recentMediaArray, const NSUInteger recentMediaIndex) {
+
+        if (cachedMediaArray == nil || cachedMediaIndex == NSNotFound) {
+            NSLog(@"Could not handle deletion for media library item with id %lld in model", itemId);
+            return;
+        }
+
+        VLCMediaLibraryMediaItem * mediaItem = cachedMediaArray[cachedMediaIndex];
+        // Notify what happened
+        [cachedMediaArray removeObjectAtIndex:cachedMediaIndex];
+
+        if (recentMediaArray != nil && recentMediaIndex != NSNotFound) {
+            [recentMediaArray removeObjectAtIndex:recentMediaIndex];
+            [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelRecentsMediaItemDeleted object:mediaItem];
+        }
+
+        switch (mediaItem.mediaType) {
+            case VLC_ML_MEDIA_TYPE_VIDEO:
+                [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaItemDeleted object:mediaItem];
+                break;
+            case VLC_ML_MEDIA_TYPE_AUDIO:
+                [self->_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaItemDeleted object:mediaItem];
+                break;
+            case VLC_ML_MEDIA_TYPE_UNKNOWN:
+                NSLog(@"Unknown type of media type encountered, don't know what to do in deletion");
+                break;
+        }
+    }];
 }
 
 @end


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.m
=====================================
@@ -89,8 +89,17 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
         NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
         [notificationCenter addObserver:self
                                selector:@selector(libraryModelUpdated:)
-                                   name:VLCLibraryModelAudioMediaListUpdated
+                                   name:VLCLibraryModelAudioMediaListReset
                                  object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelAudioItemUpdated:)
+                                   name:VLCLibraryModelAudioMediaItemUpdated
+                                 object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelAudioItemDeleted:)
+                                   name:VLCLibraryModelAudioMediaItemDeleted
+                                 object:nil];
+
         [notificationCenter addObserver:self
                                selector:@selector(libraryModelUpdated:)
                                    name:VLCLibraryModelArtistListUpdated
@@ -152,44 +161,55 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
     }
 }
 
-- (void)libraryModelUpdated:(NSNotification *)aNotification
+- (NSArray *)collectionToDisplay
 {
-    if(self.libraryModel == nil) {
-        return;
-    }
-    
-    NSArray *collectionToDisplay;
-
     switch(_currentParentType) {
         case VLC_ML_PARENT_UNKNOWN:
-            collectionToDisplay = [self.libraryModel listOfAudioMedia];
-            break;
+            return [_libraryModel listOfAudioMedia];
         case VLC_ML_PARENT_ALBUM:
-            collectionToDisplay = [self.libraryModel listOfAlbums];
-            break;
+            return [_libraryModel listOfAlbums];
         case VLC_ML_PARENT_ARTIST:
-            collectionToDisplay = [self.libraryModel listOfArtists];
-            break;
+            return [_libraryModel listOfArtists];
         case VLC_ML_PARENT_GENRE:
-            collectionToDisplay = [self.libraryModel listOfGenres];
-            break;
+            return [_libraryModel listOfGenres];
         default:
-            return;
+            return nil;
     }
+}
 
-    dispatch_async(dispatch_get_main_queue(), ^{
-        NSSet* originalCollectionSet = [[NSSet alloc] initWithArray:self->_displayedCollection];
-        NSSet* newCollectionSet = [[NSSet alloc] initWithArray:collectionToDisplay];
+- (void)libraryModelUpdated:(NSNotification * const)aNotification
+{
+    if(_libraryModel == nil) {
+        return;
+    }
 
-        if([originalCollectionSet isEqual:newCollectionSet]) {
-            return;
-        }
+    [self reloadData];
+}
+
+- (void)libraryModelAudioItemUpdated:(NSNotification * const)aNotification
+{
+    if(_libraryModel == nil) {
+        return;
+    }
+
+    NSParameterAssert(aNotification);
+    VLCMediaLibraryMediaItem * const mediaItem = (VLCMediaLibraryMediaItem * const)aNotification.object;
+    NSAssert(mediaItem != nil, @"Audio item-related notification should carry valid media item");
 
-        [self retainSelectedMediaItem];
-        self->_displayedCollection = collectionToDisplay;
-        [self reloadData];
-        [self restoreSelectionState];
-    });
+    [self reloadDataForMediaLibraryItem:mediaItem];
+}
+
+- (void)libraryModelAudioItemDeleted:(NSNotification * const)aNotification
+{
+    if(_libraryModel == nil) {
+        return;
+    }
+
+    NSParameterAssert(aNotification);
+    VLCMediaLibraryMediaItem * const mediaItem = (VLCMediaLibraryMediaItem * const)aNotification.object;
+    NSAssert(mediaItem != nil, @"Audio item-related notification should carry valid media item");
+
+    [self deleteDataForMediaLibraryItem:mediaItem];
 }
 
 - (void)retainSelectedMediaItem
@@ -420,14 +440,7 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
     return VLCLibraryTitleSortDescriptorKey;
 }
 
-- (void)reloadData
-{
-    [self retainSelectedMediaItem];
-    [self reloadViews];
-    [self restoreSelectionState];
-}
-
-- (void)reloadViews
+- (void)resetLayoutsForOperation:(void(^)(void))operation
 {
     VLCLibraryCollectionViewFlowLayout *collectionViewFlowLayout = (VLCLibraryCollectionViewFlowLayout *)_collectionView.collectionViewLayout;
     if (collectionViewFlowLayout) {
@@ -439,15 +452,87 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
         [gridModeListSelectionCollectionViewFlowLayout resetLayout];
     }
 
-    [self.collectionView reloadData];
-    [self.gridModeListTableView reloadData];
-    [self.gridModeListSelectionCollectionView reloadData];
-    [self.collectionSelectionTableView reloadData];
-    [self.groupSelectionTableView reloadData];
-    [self.songsTableView reloadData];
+    operation();
     [self setupExistingSortForTableView:_songsTableView];
 }
 
+- (void)reloadData
+{
+    [self retainSelectedMediaItem];
+    self->_displayedCollection = [self collectionToDisplay];
+    [self resetLayoutsForOperation:^{
+        [self.collectionView reloadData];
+        [self.gridModeListTableView reloadData];
+        [self.gridModeListSelectionCollectionView reloadData];
+        [self.collectionSelectionTableView reloadData];
+        [self.groupSelectionTableView reloadData];
+        [self.songsTableView reloadData];
+    }];
+    [self restoreSelectionState];
+}
+
+- (NSUInteger)indexForMediaLibraryItemWithId:(const int64_t)itemId
+{
+    return [_displayedCollection indexOfObjectPassingTest:^BOOL(VLCMediaLibraryMediaItem * const mediaItem, const NSUInteger idx, BOOL * const stop) {
+        NSAssert(mediaItem != nil, @"Cache list should not contain nil media items");
+        return mediaItem.libraryID == itemId;
+    }];
+}
+
+- (void)reloadDataForMediaLibraryItem:(VLCMediaLibraryMediaItem * const)mediaItem
+{
+    [self resetLayoutsForOperation:^{
+        const NSUInteger index = [self indexForMediaLibraryItemWithId:mediaItem.libraryID];
+        if (index == NSNotFound) {
+            return;
+        }
+
+        NSMutableArray * const mutableCollectionCopy = [self->_displayedCollection mutableCopy];
+        [mutableCollectionCopy replaceObjectAtIndex:index withObject:mediaItem];
+        self->_displayedCollection = [mutableCollectionCopy copy];
+
+        NSIndexPath * const indexPath = [NSIndexPath indexPathForItem:index inSection:0];
+        NSIndexSet * const rowIndexSet = [NSIndexSet indexSetWithIndex:index];
+
+        NSRange songsTableColumnRange = NSMakeRange(0, self->_songsTableView.numberOfColumns);
+        NSIndexSet * const songsTableColumnIndexSet = [NSIndexSet indexSetWithIndexesInRange:songsTableColumnRange];
+
+        [self.collectionView reloadItemsAtIndexPaths:[NSSet setWithObject:indexPath]];
+        [self.songsTableView reloadDataForRowIndexes:rowIndexSet columnIndexes:songsTableColumnIndexSet];
+
+        // Don't update gridModeListSelectionCollectionView, let its VLCLibraryAudioGroupDataSource do it.
+        // TODO: Stop splitting functionality for these audio source selection views between this data source
+        // TODO: and the VLCLibraryAudioGroupDataSource, it is super confusing
+
+        // Also don't update:
+        // - gridModeListTableView, as this will only show artists/genres
+        // - collectionSelectionTableView, as this will only show artists/genres/albums
+        // - groupSelectionTableView, as this shows cells for albums (and each cell has its own data source with media items)
+    }];
+}
+
+- (void)deleteDataForMediaLibraryItem:(VLCMediaLibraryMediaItem * const)mediaItem
+{
+    [self resetLayoutsForOperation:^{
+        const NSUInteger index = [self indexForMediaLibraryItemWithId:mediaItem.libraryID];
+        if (index == NSNotFound) {
+            return;
+        }
+
+        NSMutableArray * const mutableCollectionCopy = [self->_displayedCollection mutableCopy];
+        [mutableCollectionCopy removeObjectAtIndex:index];
+        self->_displayedCollection = [mutableCollectionCopy copy];
+
+        NSIndexPath * const indexPath = [NSIndexPath indexPathForItem:index inSection:0];
+        NSIndexSet * const rowIndexSet = [NSIndexSet indexSetWithIndex:index];
+
+        [self.collectionView deleteItemsAtIndexPaths:[NSSet setWithObject:indexPath]];
+        [self.songsTableView removeRowsAtIndexes:rowIndexSet withAnimation:NSTableViewAnimationSlideUp];
+
+        // Comment in reloadDataForMediaLibraryItem will be informative
+    }];
+}
+
 - (void)setAudioLibrarySegment:(VLCAudioLibrarySegment)audioLibrarySegment
 {
     if (audioLibrarySegment == _audioLibrarySegment) {


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.m
=====================================
@@ -82,7 +82,11 @@ NSString *VLCLibraryPlaceholderAudioViewIdentifier = @"VLCLibraryPlaceholderAudi
         NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
         [notificationCenter addObserver:self
                                selector:@selector(libraryModelUpdated:)
-                                   name:VLCLibraryModelAudioMediaListUpdated
+                                   name:VLCLibraryModelAudioMediaListReset
+                                 object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelUpdated:)
+                                   name:VLCLibraryModelAudioMediaItemDeleted
                                  object:nil];
     }
 


=====================================
modules/gui/macosx/library/video-library/VLCLibraryVideoCollectionViewContainerViewDataSource.m
=====================================
@@ -36,10 +36,12 @@
 
 @interface VLCLibraryVideoCollectionViewContainerViewDataSource ()
 {
-    NSArray *_collectionArray;
     VLCLibraryCollectionViewFlowLayout *_collectionViewFlowLayout;
     VLCLibraryModel *_libraryModel;
 }
+
+ at property (readwrite, atomic) NSArray *collectionArray;
+
 @end
 
 @implementation VLCLibraryVideoCollectionViewContainerViewDataSource
@@ -50,23 +52,115 @@
     if(self) {
         NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
         [notificationCenter addObserver:self
-                               selector:@selector(libraryModelUpdated:)
-                                   name:VLCLibraryModelVideoMediaListUpdated
+                               selector:@selector(libraryModelVideoListReset:)
+                                   name:VLCLibraryModelVideoMediaListReset
+                                 object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelVideoItemUpdated:)
+                                   name:VLCLibraryModelVideoMediaItemUpdated
+                                 object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelVideoItemDeleted:)
+                                   name:VLCLibraryModelVideoMediaItemDeleted
+                                 object:nil];
+
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelRecentsListReset:)
+                                   name:VLCLibraryModelRecentsMediaListReset
                                  object:nil];
         [notificationCenter addObserver:self
-                               selector:@selector(libraryModelUpdated:)
-                                   name:VLCLibraryModelRecentMediaListUpdated
+                               selector:@selector(libraryModelRecentsItemUpdated:)
+                                   name:VLCLibraryModelRecentsMediaItemUpdated
                                  object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelRecentsItemDeleted:)
+                                   name:VLCLibraryModelRecentsMediaItemDeleted
+                                 object:nil];
+
         _libraryModel = [VLCMain sharedInstance].libraryController.libraryModel;
+        self.collectionArray = [NSArray array];
     }
     return self;
 }
 
-- (void)libraryModelUpdated:(NSNotification *)aNotification
+- (NSUInteger)indexOfMediaItemInCollection:(const NSUInteger)libraryId
+{
+    return [self.collectionArray indexOfObjectPassingTest:^BOOL(VLCMediaLibraryMediaItem * const findMediaItem, const NSUInteger idx, BOOL * const stop) {
+        NSAssert(findMediaItem != nil, @"Collection should not contain nil media items");
+        return findMediaItem.libraryID == libraryId;
+    }];
+}
+
+- (void)libraryModelVideoListReset:(NSNotification * const)aNotification
+{
+    if (_groupDescriptor.group != VLCLibraryVideoLibraryGroup) {
+        return;
+    }
+
+    [self reloadData];
+}
+
+- (void)libraryModelVideoItemUpdated:(NSNotification * const)aNotification
+{
+    if (_groupDescriptor.group != VLCLibraryVideoLibraryGroup) {
+        return;
+    }
+
+    NSParameterAssert(aNotification);
+    VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
+    NSAssert(notificationMediaItem != nil, @"Media item updated notification should carry valid media item");
+
+    [self reloadDataForMediaItem:notificationMediaItem];
+}
+
+- (void)libraryModelVideoItemDeleted:(NSNotification * const)aNotification
+{
+    if (_groupDescriptor.group != VLCLibraryVideoLibraryGroup) {
+        return;
+    }
+
+    NSParameterAssert(aNotification);
+    VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
+    NSAssert(notificationMediaItem != nil, @"Media item deleted notification should carry valid media item");
+
+    [self deleteDataForMediaItem:notificationMediaItem];
+}
+
+- (void)libraryModelRecentsListReset:(NSNotification * const)aNotification
 {
+    if (_groupDescriptor.group != VLCLibraryVideoRecentsGroup) {
+        return;
+    }
+
     [self reloadData];
 }
 
+- (void)libraryModelRecentsItemUpdated:(NSNotification * const)aNotification
+{
+    if (_groupDescriptor.group != VLCLibraryVideoRecentsGroup) {
+        return;
+    }
+
+    NSParameterAssert(aNotification);
+    VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
+    NSAssert(notificationMediaItem != nil, @"Media item updated notification should carry valid media item");
+
+    [self reloadDataForMediaItem:notificationMediaItem];
+}
+
+- (void)libraryModelRecentsItemDeleted:(NSNotification * const)aNotification
+{
+    if (_groupDescriptor.group != VLCLibraryVideoRecentsGroup) {
+        return;
+    }
+
+    NSParameterAssert(aNotification);
+    VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
+    NSAssert(notificationMediaItem != nil, @"Media item deleted notification should carry valid media item");
+
+    [self deleteDataForMediaItem:notificationMediaItem];
+}
+
 - (void)reloadData
 {
     if(!_collectionView || !_groupDescriptor) {
@@ -74,18 +168,54 @@
         return;
     }
 
-    dispatch_async(dispatch_get_main_queue(), ^{
-        NSAssert(self->_groupDescriptor.libraryModelDataMethodSignature, @"Group descriptor's library model data method signature cannot be nil");
-
-        NSInvocation *modelDataInvocation = [NSInvocation invocationWithMethodSignature:self->_groupDescriptor.libraryModelDataMethodSignature];
-        modelDataInvocation.selector = self->_groupDescriptor.libraryModelDataSelector;
-        [modelDataInvocation invokeWithTarget:self->_libraryModel];
-        [modelDataInvocation getReturnValue:&self->_collectionArray];
+    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
+        switch(self->_groupDescriptor.group) {
+            case VLCLibraryVideoLibraryGroup:
+                self.collectionArray = self->_libraryModel.listOfVideoMedia;
+                break;
+            case VLCLibraryVideoRecentsGroup:
+                self.collectionArray = self->_libraryModel.listOfRecentMedia;
+                break;
+            default:
+                return;
+        }
 
-        [self->_collectionView reloadData];
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [self->_collectionView reloadData];
+        });
     });
 }
 
+- (void)reloadDataForMediaItem:(VLCMediaLibraryMediaItem * const)mediaItem
+{
+    NSUInteger mediaItemIndex = [self indexOfMediaItemInCollection:mediaItem.libraryID];
+    if (mediaItemIndex == NSNotFound) {
+        return;
+    }
+
+    NSMutableArray * const mutableCollectionCopy = [self.collectionArray mutableCopy];
+    [mutableCollectionCopy replaceObjectAtIndex:mediaItemIndex withObject:mediaItem];
+    self.collectionArray = [mutableCollectionCopy copy];
+
+    NSIndexPath * const indexPath = [NSIndexPath indexPathForItem:mediaItemIndex inSection:0];
+    [self->_collectionView reloadItemsAtIndexPaths:[NSSet setWithObject:indexPath]];
+}
+
+- (void)deleteDataForMediaItem:(VLCMediaLibraryMediaItem * const)mediaItem
+{
+    NSUInteger mediaItemIndex = [self indexOfMediaItemInCollection:mediaItem.libraryID];
+    if (mediaItemIndex == NSNotFound) {
+        return;
+    }
+
+    NSMutableArray * const mutableCollectionCopy = [self.collectionArray mutableCopy];
+    [mutableCollectionCopy removeObjectAtIndex:mediaItemIndex];
+    self.collectionArray = [mutableCollectionCopy copy];
+
+    NSIndexPath * const indexPath = [NSIndexPath indexPathForItem:mediaItemIndex inSection:0];
+    [self->_collectionView deleteItemsAtIndexPaths:[NSSet setWithObject:indexPath]];
+}
+
 - (void)setGroupDescriptor:(VLCLibraryVideoCollectionViewGroupDescriptor *)groupDescriptor
 {
     if(!groupDescriptor) {
@@ -130,14 +260,14 @@
         return 0;
     }
 
-    return _collectionArray.count;
+    return self.collectionArray.count;
 }
 
 - (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView
      itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath
 {
     VLCLibraryCollectionViewItem *viewItem = [collectionView makeItemWithIdentifier:VLCLibraryCellIdentifier forIndexPath:indexPath];
-    viewItem.representedItem = _collectionArray[indexPath.item];
+    viewItem.representedItem = self.collectionArray[indexPath.item];
     return viewItem;
 }
 
@@ -156,7 +286,7 @@ viewForSupplementaryElementOfKind:(NSCollectionViewSupplementaryElementKind)kind
     } else if ([kind isEqualToString:VLCLibraryCollectionViewMediaItemSupplementaryDetailViewKind]) {
         VLCLibraryCollectionViewMediaItemSupplementaryDetailView* mediaItemSupplementaryDetailView = [collectionView makeSupplementaryViewOfKind:kind withIdentifier:VLCLibraryCollectionViewMediaItemSupplementaryDetailViewKind forIndexPath:indexPath];
 
-        mediaItemSupplementaryDetailView.representedMediaItem = _collectionArray[indexPath.item];
+        mediaItemSupplementaryDetailView.representedMediaItem = self.collectionArray[indexPath.item];
         mediaItemSupplementaryDetailView.selectedItem = [collectionView itemAtIndexPath:indexPath];
         return mediaItemSupplementaryDetailView;
     }
@@ -167,7 +297,7 @@ viewForSupplementaryElementOfKind:(NSCollectionViewSupplementaryElementKind)kind
 - (id<VLCMediaLibraryItemProtocol>)libraryItemAtIndexPath:(NSIndexPath *)indexPath
                                         forCollectionView:(NSCollectionView *)collectionView
 {
-    return _collectionArray[indexPath.item];
+    return self.collectionArray[indexPath.item];
 }
 
 @end


=====================================
modules/gui/macosx/library/video-library/VLCLibraryVideoGroupDescriptor.h
=====================================
@@ -38,7 +38,6 @@ NS_ASSUME_NONNULL_BEGIN
 @property (readonly) VLCLibraryVideoGroup group;
 @property (readonly) SEL libraryModelDataSelector;
 @property (readonly) NSMethodSignature *libraryModelDataMethodSignature;
- at property (readonly) NSNotificationName libraryModelUpdatedNotificationName;
 @property (readonly) NSString *name;
 @property (readonly) BOOL isHorizontalBarCollectionView;
 


=====================================
modules/gui/macosx/library/video-library/VLCLibraryVideoGroupDescriptor.m
=====================================
@@ -37,13 +37,11 @@
 
         switch (_group) {
             case VLCLibraryVideoRecentsGroup:
-                _libraryModelUpdatedNotificationName = VLCLibraryModelRecentMediaListUpdated;
                 _libraryModelDataSelector = @selector(listOfRecentMedia);
                 _isHorizontalBarCollectionView = YES;
                 _name = _NS("Recents");
                 break;
             case VLCLibraryVideoLibraryGroup:
-                _libraryModelUpdatedNotificationName = VLCLibraryModelVideoMediaListUpdated;
                 _libraryModelDataSelector = @selector(listOfVideoMedia);
                 _isHorizontalBarCollectionView = NO;
                 _name = _NS("Library");


=====================================
modules/gui/macosx/library/video-library/VLCLibraryVideoTableViewDataSource.m
=====================================
@@ -54,22 +54,128 @@
     if(self) {
         NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
         [notificationCenter addObserver:self
-                               selector:@selector(libraryModelUpdated:)
-                                   name:VLCLibraryModelVideoMediaListUpdated
+                               selector:@selector(libraryModelVideoListReset:)
+                                   name:VLCLibraryModelVideoMediaListReset
                                  object:nil];
         [notificationCenter addObserver:self
-                               selector:@selector(libraryModelUpdated:)
-                                   name:VLCLibraryModelRecentMediaListUpdated
+                               selector:@selector(libraryModelVideoItemUpdated:)
+                                   name:VLCLibraryModelVideoMediaItemUpdated
+                                 object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelVideoItemDeleted:)
+                                   name:VLCLibraryModelVideoMediaItemDeleted
+                                 object:nil];
+
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelRecentsListReset:)
+                                   name:VLCLibraryModelRecentsMediaListReset
+                                 object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelRecentsItemUpdated:)
+                                   name:VLCLibraryModelRecentsMediaItemUpdated
+                                 object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelRecentsItemDeleted:)
+                                   name:VLCLibraryModelRecentsMediaItemDeleted
                                  object:nil];
     }
     return self;
 }
 
-- (void)libraryModelUpdated:(NSNotification *)aNotification
+- (NSUInteger)indexOfMediaItem:(const NSUInteger)libraryId inArray:(NSArray const *)array
+{
+    return [array indexOfObjectPassingTest:^BOOL(VLCMediaLibraryMediaItem * const findMediaItem, const NSUInteger idx, BOOL * const stop) {
+        NSAssert(findMediaItem != nil, @"Collection should not contain nil media items");
+        return findMediaItem.libraryID == libraryId;
+    }];
+}
+
+- (void)libraryModelVideoListReset:(NSNotification * const)aNotification
+{
+    if (_groupsTableView.selectedRow == -1 ||
+        _groupsTableView.selectedRow != VLCLibraryVideoLibraryGroup - 1) { // Row 0 == second value in enum, so compensate
+
+        return;
+    }
+
+    [self reloadData];
+}
+
+- (void)libraryModelVideoItemUpdated:(NSNotification * const)aNotification
 {
+    if (_groupsTableView.selectedRow == -1 ||
+        _groupsTableView.selectedRow != VLCLibraryVideoLibraryGroup - 1) { // Row 0 == second value in enum, so compensate
+
+        return;
+    }
+
+    NSParameterAssert(aNotification);
+    VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
+    NSAssert(notificationMediaItem != nil, @"Media item updated notification should carry valid media item");
+
+    [self reloadDataForMediaItem:notificationMediaItem
+                    inVideoGroup:VLCLibraryVideoLibraryGroup];
+}
+
+- (void)libraryModelVideoItemDeleted:(NSNotification * const)aNotification
+{
+    if (_groupsTableView.selectedRow == -1 ||
+        _groupsTableView.selectedRow != VLCLibraryVideoLibraryGroup - 1) { // Row 0 == second value in enum, so compensate
+
+        return;
+    }
+
+    NSParameterAssert(aNotification);
+    VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
+    NSAssert(notificationMediaItem != nil, @"Media item deleted notification should carry valid media item");
+
+    [self deleteDataForMediaItem:notificationMediaItem
+                    inVideoGroup:VLCLibraryVideoLibraryGroup];
+}
+
+- (void)libraryModelRecentsListReset:(NSNotification * const)aNotification
+{
+    if (_groupsTableView.selectedRow == -1 ||
+        _groupsTableView.selectedRow != VLCLibraryVideoRecentsGroup - 1) { // Row 0 == second value in enum, so compensate
+
+        return;
+    }
+
     [self reloadData];
 }
 
+- (void)libraryModelRecentsItemUpdated:(NSNotification * const)aNotification
+{
+    if (_groupsTableView.selectedRow == -1 ||
+        _groupsTableView.selectedRow != VLCLibraryVideoRecentsGroup - 1) { // Row 0 == second value in enum, so compensate
+
+        return;
+    }
+
+    NSParameterAssert(aNotification);
+    VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
+    NSAssert(notificationMediaItem != nil, @"Media item updated notification should carry valid media item");
+
+    [self reloadDataForMediaItem:notificationMediaItem
+                    inVideoGroup:VLCLibraryVideoRecentsGroup];
+}
+
+- (void)libraryModelRecentsItemDeleted:(NSNotification * const)aNotification
+{
+    if (_groupsTableView.selectedRow == -1 ||
+        _groupsTableView.selectedRow != VLCLibraryVideoRecentsGroup - 1) { // Row 0 == second value in enum, so compensate
+
+        return;
+    }
+
+    NSParameterAssert(aNotification);
+    VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
+    NSAssert(notificationMediaItem != nil, @"Media item deleted notification should carry valid media item");
+
+    [self deleteDataForMediaItem:notificationMediaItem
+                    inVideoGroup:VLCLibraryVideoRecentsGroup];
+}
+
 - (void)reloadData
 {
     if(!_libraryModel) {
@@ -78,12 +184,85 @@
     
     [_collectionViewFlowLayout resetLayout];
     
-    dispatch_async(dispatch_get_main_queue(), ^{
-        self->_recentsArray = [self->_libraryModel listOfRecentMedia];
-        self->_libraryArray = [self->_libraryModel listOfVideoMedia];
-        [self->_groupsTableView reloadData];
-        [self->_groupSelectionTableView reloadData];
-    });
+    self->_recentsArray = [self.libraryModel listOfRecentMedia];
+    self->_libraryArray = [self.libraryModel listOfVideoMedia];
+    [self->_groupSelectionTableView reloadData];
+}
+
+- (void)changeDataForSpecificMediaItem:(VLCMediaLibraryMediaItem * const)mediaItem
+                          inVideoGroup:(VLCLibraryVideoGroup)group
+                        arrayOperation:(void(^)(const NSMutableArray*, const NSUInteger))arrayOperation
+                     completionHandler:(void(^)(const NSIndexSet*))completionHandler
+{
+    NSMutableArray *groupMutableCopyArray;
+    switch(group) {
+        case VLCLibraryVideoLibraryGroup:
+            groupMutableCopyArray = [_libraryArray mutableCopy];
+            break;
+        case VLCLibraryVideoRecentsGroup:
+            groupMutableCopyArray = [_recentsArray mutableCopy];
+            break;
+        default:
+            return;
+    }
+
+    NSUInteger mediaItemIndex = [self indexOfMediaItem:mediaItem.libraryID inArray:groupMutableCopyArray];
+    if (mediaItemIndex == NSNotFound) {
+        return;
+    }
+
+    arrayOperation(groupMutableCopyArray, mediaItemIndex);
+    switch(group) {
+        case VLCLibraryVideoLibraryGroup:
+            _libraryArray = [groupMutableCopyArray copy];
+            break;
+        case VLCLibraryVideoRecentsGroup:
+            _recentsArray = [groupMutableCopyArray copy];
+            break;
+        default:
+            return;
+    }
+
+    NSIndexSet * const rowIndexSet = [NSIndexSet indexSetWithIndex:mediaItemIndex];
+    completionHandler(rowIndexSet);
+}
+
+- (void)reloadDataForMediaItem:(VLCMediaLibraryMediaItem * const)mediaItem
+                  inVideoGroup:(VLCLibraryVideoGroup)group
+{
+    [self changeDataForSpecificMediaItem:mediaItem
+                            inVideoGroup:group
+                          arrayOperation:^(NSMutableArray * const mediaArray, const NSUInteger mediaItemIndex) {
+
+        [mediaArray replaceObjectAtIndex:mediaItemIndex withObject:mediaItem];
+
+    } completionHandler:^(NSIndexSet * const rowIndexSet) {
+
+        // Don't regenerate the groups by index as these do not change according to the notification
+        // Stick to the selection table view
+        NSRange columnRange = NSMakeRange(0, self->_groupsTableView.numberOfColumns);
+        NSIndexSet * const columnIndexSet = [NSIndexSet indexSetWithIndexesInRange:columnRange];
+        [self->_groupSelectionTableView reloadDataForRowIndexes:rowIndexSet columnIndexes:columnIndexSet];
+
+    }];
+}
+
+- (void)deleteDataForMediaItem:(VLCMediaLibraryMediaItem * const)mediaItem
+                  inVideoGroup:(VLCLibraryVideoGroup)group
+{
+    [self changeDataForSpecificMediaItem:mediaItem
+                            inVideoGroup:group
+                          arrayOperation:^(NSMutableArray * const mediaArray, const NSUInteger mediaItemIndex) {
+
+        [mediaArray removeObjectAtIndex:mediaItemIndex];
+
+    } completionHandler:^(NSIndexSet * const rowIndexSet){
+
+        // Don't regenerate the groups by index as these do not change according to the notification
+        // Stick to the selection table view
+        [self->_groupSelectionTableView removeRowsAtIndexes:rowIndexSet withAnimation:NSTableViewAnimationSlideUp];
+
+    }];
 }
 
 #pragma mark - table view data source and delegation


=====================================
modules/gui/macosx/library/video-library/VLCLibraryVideoViewController.m
=====================================
@@ -65,7 +65,11 @@
         NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
         [notificationCenter addObserver:self
                                selector:@selector(libraryModelUpdated:)
-                                   name:VLCLibraryModelVideoMediaListUpdated
+                                   name:VLCLibraryModelVideoMediaListReset
+                                 object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(libraryModelUpdated:)
+                                   name:VLCLibraryModelVideoMediaItemDeleted
                                  object:nil];
     }
 
@@ -218,8 +222,7 @@
 - (void)libraryModelUpdated:(NSNotification *)aNotification
 {
     NSParameterAssert(aNotification);
-    VLCLibraryModel *model = (VLCLibraryModel *)aNotification.object;
-    NSAssert(model, @"Notification object should be a VLCLibraryModel");
+    VLCLibraryModel *model = VLCMain.sharedInstance.libraryController.libraryModel;
     NSArray<VLCMediaLibraryMediaItem *> * videoList = model.listOfVideoMedia;
 
     if (_segmentedTitleControl.selectedSegment == VLCLibraryVideoSegment &&



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2f7f5f32ad91eaecdc68d836be1e94ad2112f8c0...4c6222e6c33501aac8c68b7d4596151d588cf16b

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2f7f5f32ad91eaecdc68d836be1e94ad2112f8c0...4c6222e6c33501aac8c68b7d4596151d588cf16b
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