[vlc-commits] [Git][videolan/vlc][master] 4 commits: macosx: Fix handling of item added events for shows

Steve Lhomme (@robUx4) gitlab at videolan.org
Thu Aug 28 08:52:49 UTC 2025



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
7a3c127c by Claudio Cambra at 2025-08-28T08:37:46+00:00
macosx: Fix handling of item added events for shows

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

- - - - -
b9089b3a by Claudio Cambra at 2025-08-28T08:37:46+00:00
macosx: Add convenience method to initialise show from library ID

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

- - - - -
45642105 by Claudio Cambra at 2025-08-28T08:37:46+00:00
macosx: Granularly handle show item updates in library model, notify

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

- - - - -
1610f7c5 by Claudio Cambra at 2025-08-28T08:37:46+00:00
macosx: Granularly update show library views

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

- - - - -


5 changed files:

- modules/gui/macosx/library/VLCLibraryDataTypes.h
- modules/gui/macosx/library/VLCLibraryDataTypes.m
- modules/gui/macosx/library/VLCLibraryModel.h
- modules/gui/macosx/library/VLCLibraryModel.m
- modules/gui/macosx/library/video-library/VLCLibraryShowsDataSource.m


Changes:

=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.h
=====================================
@@ -214,6 +214,7 @@ typedef NS_ENUM(NSUInteger, VLCMediaLibraryParentGroupType) {
 
 @interface VLCMediaLibraryShow : VLCAbstractMediaLibraryItem<VLCMediaLibraryItemProtocol>
 
++ (nullable instancetype)showWithLibraryId:(int64_t)libraryId;
 - (instancetype)initWithShow:(struct vlc_ml_show_t *)p_show;
 
 @property (readonly) NSString *name;


=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.m
=====================================
@@ -1671,6 +1671,19 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
 
 @synthesize episodes = _episodes;
 
++ (nullable instancetype)showWithLibraryId:(const int64_t)libraryId
+{
+    vlc_medialibrary_t * const p_mediaLibrary = getMediaLibrary();
+    if (p_mediaLibrary == NULL) {
+        return nil;
+    }
+    vlc_ml_show_t * const p_show = vlc_ml_get_show(p_mediaLibrary, libraryId);
+    if (p_show == NULL) {
+        return nil;
+    }
+    return [[VLCMediaLibraryShow alloc] initWithShow:p_show];
+}
+
 - (instancetype)initWithShow:(struct vlc_ml_show_t *)p_show
 {
     self = [super init];


=====================================
modules/gui/macosx/library/VLCLibraryModel.h
=====================================
@@ -56,6 +56,7 @@ extern NSString * const VLCLibraryModelArtistDeleted;
 extern NSString * const VLCLibraryModelGenreDeleted;
 extern NSString * const VLCLibraryModelGroupDeleted;
 extern NSString * const VLCLibraryModelPlaylistDeleted;
+extern NSString * const VLCLibraryModelShowDeleted;
 
 extern NSString * const VLCLibraryModelAudioMediaItemUpdated;
 extern NSString * const VLCLibraryModelVideoMediaItemUpdated;
@@ -66,6 +67,7 @@ extern NSString * const VLCLibraryModelArtistUpdated;
 extern NSString * const VLCLibraryModelGenreUpdated;
 extern NSString * const VLCLibraryModelGroupUpdated;
 extern NSString * const VLCLibraryModelPlaylistUpdated;
+extern NSString * const VLCLibraryModelShowUpdated;
 
 extern NSString * const VLCLibraryModelDiscoveryStarted;
 extern NSString * const VLCLibraryModelDiscoveryProgress;


=====================================
modules/gui/macosx/library/VLCLibraryModel.m
=====================================
@@ -59,6 +59,7 @@ NSString * const VLCLibraryModelArtistDeleted = @"VLCLibraryModelArtistDeleted";
 NSString * const VLCLibraryModelGenreDeleted = @"VLCLibraryModelGenreDeleted";
 NSString * const VLCLibraryModelGroupDeleted = @"VLCLibraryModelGroupDeleted";
 NSString * const VLCLibraryModelPlaylistDeleted = @"VLCLibraryModelPlaylistDeleted";
+NSString * const VLCLibraryModelShowDeleted = @"VLCLibraryModelShowDeleted";
 
 NSString * const VLCLibraryModelAudioMediaItemUpdated = @"VLCLibraryModelAudioMediaItemUpdated";
 NSString * const VLCLibraryModelVideoMediaItemUpdated = @"VLCLibraryModelVideoMediaItemUpdated";
@@ -69,6 +70,7 @@ NSString * const VLCLibraryModelArtistUpdated = @"VLCLibraryModelArtistUpdated";
 NSString * const VLCLibraryModelGenreUpdated = @"VLCLibraryModelGenreUpdated";
 NSString * const VLCLibraryModelGroupUpdated = @"VLCLibraryModelGroupUpdated";
 NSString * const VLCLibraryModelPlaylistUpdated = @"VLCLibraryModelPlaylistUpdated";
+NSString * const VLCLibraryModelShowUpdated = @"VLCLibraryModelShowUpdated";
 
 NSString * const VLCLibraryModelDiscoveryStarted = @"VLCLibraryModelDiscoveryStarted";
 NSString * const VLCLibraryModelDiscoveryProgress = @"VLCLibraryModelDiscoveryProgress";
@@ -790,14 +792,14 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 
     if (p_media->i_type == VLC_ML_MEDIA_TYPE_AUDIO || p_media->i_type == VLC_ML_MEDIA_TYPE_UNKNOWN) {
         [self resetCachedListOfAudioMedia];
-
-        if (p_media->i_subtype == VLC_ML_MEDIA_SUBTYPE_SHOW_EPISODE) {
-            [self resetCachedListOfShows];
-        }
     }
 
     if (p_media->i_type == VLC_ML_MEDIA_TYPE_VIDEO || p_media->i_type == VLC_ML_MEDIA_TYPE_UNKNOWN) {
         [self resetCachedListOfVideoMedia];
+
+        if (p_media->i_subtype == VLC_ML_MEDIA_SUBTYPE_SHOW_EPISODE) {
+            [self resetCachedListOfShows];
+        }
     }
 }
 
@@ -965,7 +967,16 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     [self.changeDelegate notifyChange:VLCLibraryModelRecentAudioMediaListReset withObject:self];
 }
 
-- (void)performActionOnMediaItemInCache:(const int64_t)libraryId action:(void (^)(const NSMutableArray*, const NSUInteger, const NSMutableArray*, const NSUInteger))action
+- (void)performActionOnMediaItemInCache:(const int64_t)libraryId 
+                                 action:(void (^)(
+                                    NSMutableArray * const,
+                                    const NSUInteger,
+                                    NSMutableArray * const,
+                                    const NSUInteger,
+                                    NSMutableArray * const,
+                                    const NSUInteger,
+                                    const NSUInteger
+                                 ))action
 {
     dispatch_async(_mediaItemCacheModificationQueue, ^{
         BOOL (^idCheckBlock)(VLCMediaLibraryMediaItem * const, const NSUInteger, BOOL * const) = ^BOOL(VLCMediaLibraryMediaItem * const mediaItem, const NSUInteger idx, BOOL * const stop) {
@@ -981,8 +992,19 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         NSMutableArray * const videoMutable = self.cachedVideoMedia.mutableCopy;
         const NSUInteger videoIndex = [videoMutable indexOfObjectPassingTest:idCheckBlock];
         if (videoIndex != NSNotFound) {
+            NSMutableArray * const showsMutable = self.cachedListOfShows.mutableCopy;
+            NSInteger showIndex = NSNotFound;
+            NSInteger episodeIndex = NSNotFound;
+            for (VLCMediaLibraryShow * const show in showsMutable) {
+                episodeIndex = [show.episodes indexOfObjectPassingTest:idCheckBlock];
+                showIndex = [showsMutable indexOfObject:show];
+                if (episodeIndex != NSNotFound) {
+                    break;
+                }
+            }
+
             dispatch_sync(dispatch_get_main_queue(), ^{
-                action(videoMutable, videoIndex, recentsMutable, recentsIndex);
+                action(videoMutable, videoIndex, recentsMutable, recentsIndex, showsMutable, showIndex, episodeIndex);
                 self.cachedVideoMedia = videoMutable.copy;
                 self.cachedRecentMedia = recentsMutable.copy;
             });
@@ -997,14 +1019,14 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         const NSUInteger audioIndex = [self.cachedAudioMedia indexOfObjectPassingTest:idCheckBlock];
         if (audioIndex != NSNotFound) {
             dispatch_sync(dispatch_get_main_queue(), ^{
-                action(audioMutable, audioIndex, recentAudiosMutable, recentAudiosIndex);
+                action(audioMutable, audioIndex, recentAudiosMutable, recentAudiosIndex, nil, NSNotFound, NSNotFound);
                 self.cachedAudioMedia = audioMutable.copy;
                 self.cachedRecentAudioMedia = recentsMutable.copy;
             });
             return;
         }
 
-        action(nil, NSNotFound, nil, NSNotFound);
+        action(nil, NSNotFound, nil, NSNotFound, nil, NSNotFound, NSNotFound);
     });
 }
 
@@ -1020,8 +1042,15 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         return;
     }
 
-    [self performActionOnMediaItemInCache:itemId action:^(NSMutableArray * const cachedMediaArray, const NSUInteger cachedMediaIndex, NSMutableArray * const recentMediaArray, const NSUInteger recentMediaIndex) {
-
+    [self performActionOnMediaItemInCache:itemId action:^(
+        NSMutableArray * const cachedMediaArray,
+        const NSUInteger cachedMediaIndex,
+        NSMutableArray * const recentMediaArray,
+        const NSUInteger recentMediaIndex,
+        NSMutableArray * const showsArray,
+        const NSUInteger showIndex,
+        const NSUInteger showEpisodeIndex
+    ) {
         if (cachedMediaArray == nil || cachedMediaIndex == NSNotFound) {
             NSLog(@"Could not handle update for media library item with id %lld in model", itemId);
             return;
@@ -1047,6 +1076,14 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
             }
         }
 
+        if (showsArray != nil && showIndex != NSNotFound) {
+            // An episode has changed. Refresh the whole show.
+            VLCMediaLibraryShow * const staleShow = showsArray[showIndex];
+            VLCMediaLibraryShow * const updatedShow = [VLCMediaLibraryShow showWithLibraryId:staleShow.libraryID];
+            [showsArray replaceObjectAtIndex:showIndex withObject:updatedShow];
+            [self.changeDelegate notifyChange:VLCLibraryModelShowUpdated withObject:updatedShow];
+        }
+
         switch (mediaItem.mediaType) {
             case VLC_ML_MEDIA_TYPE_VIDEO:
                 [self.changeDelegate notifyChange:VLCLibraryModelVideoMediaItemUpdated 
@@ -1060,10 +1097,6 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
                 NSLog(@"Unknown type of media type encountered, don't know what to do in update");
                 break;
         }
-
-        if (mediaItem.mediaSubType == VLC_ML_MEDIA_SUBTYPE_SHOW_EPISODE) {
-            [self resetCachedListOfShows];
-        }
     }];
 }
 
@@ -1073,7 +1106,15 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 
     const int64_t itemId = p_event->modification.i_entity_id;
 
-    [self performActionOnMediaItemInCache:itemId action:^(NSMutableArray * const cachedMediaArray, const NSUInteger cachedMediaIndex, NSMutableArray * const recentMediaArray, const NSUInteger recentMediaIndex) {
+    [self performActionOnMediaItemInCache:itemId action:^(
+        NSMutableArray * const cachedMediaArray,
+        const NSUInteger cachedMediaIndex,
+        NSMutableArray * const recentMediaArray,
+        const NSUInteger recentMediaIndex,
+        NSMutableArray * const showsArray,
+        const NSUInteger showIndex,
+        const NSUInteger showEpisodeIndex
+    ) {
 
         if (cachedMediaArray == nil || cachedMediaIndex == NSNotFound) {
             NSLog(@"Could not handle deletion for media library item with id %lld in model", itemId);
@@ -1101,6 +1142,18 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
             }
         }
 
+        if (showsArray != nil && showIndex != NSNotFound) {
+            // An episode has changed. Refresh the whole show.
+            VLCMediaLibraryShow * const staleShow = showsArray[showIndex];
+            VLCMediaLibraryShow * const updatedShow = [VLCMediaLibraryShow showWithLibraryId:staleShow.libraryID];
+            if (updatedShow == nil || updatedShow.episodeCount == 0) {
+                [self.changeDelegate notifyChange:VLCLibraryModelShowDeleted withObject:@(staleShow.libraryID)];
+            } else {
+                [showsArray replaceObjectAtIndex:showIndex withObject:updatedShow];
+                [self.changeDelegate notifyChange:VLCLibraryModelShowUpdated withObject:updatedShow];
+            }
+        }
+
         switch (mediaItem.mediaType) {
             case VLC_ML_MEDIA_TYPE_VIDEO:
                 [self.changeDelegate notifyChange:VLCLibraryModelVideoMediaItemDeleted
@@ -1114,10 +1167,6 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
                 NSLog(@"Unknown type of media type encountered, don't know what to do in deletion");
                 break;
         }
-
-        if (mediaItem.mediaSubType == VLC_ML_MEDIA_SUBTYPE_SHOW_EPISODE) {
-            [self resetCachedListOfShows];
-        }
     }];
 }
 


=====================================
modules/gui/macosx/library/video-library/VLCLibraryShowsDataSource.m
=====================================
@@ -22,6 +22,7 @@
 
 #import "VLCLibraryShowsDataSource.h"
 
+#import "library/VLCLibraryDataTypes.h"
 #import "library/VLCLibraryModel.h"
 
 @implementation VLCLibraryShowsDataSource
@@ -43,6 +44,14 @@
                            selector:@selector(libraryModelShowsListReset:)
                                name:VLCLibraryModelListOfShowsReset
                              object:nil];
+    [notificationCenter addObserver:self
+                           selector:@selector(libraryModelShowDeleted:)
+                               name:VLCLibraryModelShowDeleted
+                             object:nil];
+    [notificationCenter addObserver:self
+                           selector:@selector(libraryModelShowUpdated:)
+                               name:VLCLibraryModelShowUpdated
+                             object:nil];
 
     [self reloadData];
 }
@@ -67,4 +76,50 @@
     return VLCMediaLibraryParentGroupTypeShow;
 }
 
+- (void)libraryModelShowUpdated:(NSNotification *)notification
+{
+    VLCMediaLibraryShow * const show = notification.object;
+    NSIndexPath * const indexPath = [self indexPathForLibraryItem:show];
+
+    if (indexPath != nil) {
+        [self.collectionView reloadItemsAtIndexPaths:[NSSet setWithObject:indexPath]];
+    }
+
+    const NSInteger rowIndex = [self rowForLibraryItem:show];
+    if (rowIndex == NSNotFound) {
+        return;
+    }
+
+    const NSInteger selectedMasterRow = self.masterTableView.selectedRow;
+    [self.masterTableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:rowIndex]
+                                    columnIndexes:[NSIndexSet indexSetWithIndex:0]];
+
+    if (rowIndex == selectedMasterRow && self.masterTableView.selectedRow != selectedMasterRow) {
+        [self.masterTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedMasterRow]
+                          byExtendingSelection:NO];
+    } else {
+        [self.detailTableView reloadData];
+    }
+}
+
+- (void)libraryModelShowDeleted:(NSNotification *)notification
+{
+    NSNumber * const showIdNumber = notification.object;
+    const NSInteger showLibraryId = showIdNumber.integerValue;
+    const NSInteger rowIndex = [self.backingArray indexOfObjectPassingTest:^BOOL(VLCMediaLibraryShow * const show, const NSUInteger idx, BOOL * const stop) {
+        return show.libraryID == showLibraryId;
+    }];
+    if (rowIndex == NSNotFound) {
+        return;
+    }
+
+    NSIndexPath * const indexPath = [NSIndexPath indexPathForItem:0 inSection:rowIndex];
+    if (indexPath != nil) {
+        [self.collectionView deleteItemsAtIndexPaths:[NSSet setWithObject:indexPath]];
+    }
+
+    [self.masterTableView removeRowsAtIndexes:[NSIndexSet indexSetWithIndex:rowIndex]
+                                withAnimation:NSTableViewAnimationEffectFade];
+}
+
 @end



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2976ba320bfbf6d52d8df7b2d6609d54779daea6...1610f7c54264cd50d8d05afc88fa1d3529b645ff

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2976ba320bfbf6d52d8df7b2d6609d54779daea6...1610f7c54264cd50d8d05afc88fa1d3529b645ff
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