Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
2765dfca by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Add starter VLCMediaLibraryFolderObserver

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
16317f0b by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Given an NSURL, create an fs event stream in media library folder 
observer

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
992b3e40 by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Generate and store folder observers for each ml entry point in library 
model

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
d1349cb0 by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Emit notification when receiving fs event on observed folder

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
1145cbdc by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Fix general issues around core foundation types handling in folder 
observer

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
5e28d09b by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Do not do anything if fs events count is 0

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
0e9077fd by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Refresh observers on monitored folders refresh

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
f76058b3 by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Ensure message is valid before trying to remove it

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
3a5ec9e8 by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Refresh monitored folder in library controller after receiving 
notification

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
ac292499 by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Store and retrieve last fs event id to get events since last check

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
b33b59d4 by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Fix warning regarding const fs context

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
b3f9613c by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Prevent crash from event ids being deallocated during access

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -


7 changed files:

- extras/package/macosx/VLC.xcodeproj/project.pbxproj
- modules/gui/macosx/Makefile.am
- modules/gui/macosx/library/VLCLibraryController.m
- modules/gui/macosx/library/VLCLibraryModel.m
- + modules/gui/macosx/library/VLCMediaLibraryFolderObserver.h
- + modules/gui/macosx/library/VLCMediaLibraryFolderObserver.m
- modules/gui/macosx/views/VLCStatusNotifierView.m


Changes:

=====================================
extras/package/macosx/VLC.xcodeproj/project.pbxproj
=====================================
@@ -143,6 +143,7 @@
                53B447CA2939823E00857588 /* 
VLCLibrarySongsTableViewSongPlayingTableCellView.m in Sources */ = {isa = 
PBXBuildFile; fileRef = 53B447C92939823E00857588 /* 
VLCLibrarySongsTableViewSongPlayingTableCellView.m */; };
                53B447F9293BB47B00857588 /* VLCLibraryVideoDataSource.m in 
Sources */ = {isa = PBXBuildFile; fileRef = 53B447F3293BB47A00857588 /* 
VLCLibraryVideoDataSource.m */; };
                53B447FA293BB47B00857588 /* VLCLibraryVideoGroupDescriptor.m in 
Sources */ = {isa = PBXBuildFile; fileRef = 53B447F4293BB47A00857588 /* 
VLCLibraryVideoGroupDescriptor.m */; };
+               53BDE19F2D5C8D1C00254560 /* VLCMediaLibraryFolderObserver.m in 
Sources */ = {isa = PBXBuildFile; fileRef = 53BDE19E2D5C8D1C00254560 /* 
VLCMediaLibraryFolderObserver.m */; };
                53C1EF8B2B466B13001AEEF5 /* 
VLCLibraryHomeViewVideoGridContainerView.m in Sources */ = {isa = PBXBuildFile; 
fileRef = 53C1EF852B466B13001AEEF5 /* 
VLCLibraryHomeViewVideoGridContainerView.m */; };
                53C1EF8C2B466B13001AEEF5 /* 
VLCLibraryHomeViewStackViewController.m in Sources */ = {isa = PBXBuildFile; 
fileRef = 53C1EF862B466B13001AEEF5 /* VLCLibraryHomeViewStackViewController.m 
*/; };
                53CBE30B2C159A4D006BF2E3 /* VLCNoResultsLabel.m in Sources */ = 
{isa = PBXBuildFile; fileRef = 53CBE30A2C159A4D006BF2E3 /* VLCNoResultsLabel.m 
*/; };
@@ -445,6 +446,8 @@
                53B447F0293BB47A00857588 /* VLCLibraryVideoGroupDescriptor.h */ 
= {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = 
sourcecode.c.h; path = VLCLibraryVideoGroupDescriptor.h; sourceTree = 
"<group>"; };
                53B447F3293BB47A00857588 /* VLCLibraryVideoDataSource.m */ = 
{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = 
sourcecode.c.objc; path = VLCLibraryVideoDataSource.m; sourceTree = "<group>"; 
};
                53B447F4293BB47A00857588 /* VLCLibraryVideoGroupDescriptor.m */ 
= {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = 
sourcecode.c.objc; path = VLCLibraryVideoGroupDescriptor.m; sourceTree = 
"<group>"; };
+               53BDE19D2D5C8D1C00254560 /* VLCMediaLibraryFolderObserver.h */ 
= {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = 
VLCMediaLibraryFolderObserver.h; sourceTree = "<group>"; };
+               53BDE19E2D5C8D1C00254560 /* VLCMediaLibraryFolderObserver.m */ 
= {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = 
VLCMediaLibraryFolderObserver.m; sourceTree = "<group>"; };
                53BFB1E02A6A72160065EA7A /* VLCLibraryAudioGroupHeaderView.xib 
*/ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = 
VLCLibraryAudioGroupHeaderView.xib; sourceTree = "<group>"; };
                53C1EF842B466B13001AEEF5 /* VLCLibraryHomeViewContainerView.h 
*/ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = 
sourcecode.c.h; path = VLCLibraryHomeViewContainerView.h; sourceTree = 
"<group>"; };
                53C1EF852B466B13001AEEF5 /* 
VLCLibraryHomeViewVideoGridContainerView.m */ = {isa = PBXFileReference; 
fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = 
VLCLibraryHomeViewVideoGridContainerView.m; sourceTree = "<group>"; };
@@ -1431,6 +1434,8 @@
                                53D021332CC225C6003C008F /* 
VLCLibraryWindowTitlesSidebarViewController.m */,
                                53F020A22A91D4A100E79705 /* 
VLCLibraryWindowToolbarDelegate.h */,
                                53F020A32A91D4A100E79705 /* 
VLCLibraryWindowToolbarDelegate.m */,
+                               53BDE19D2D5C8D1C00254560 /* 
VLCMediaLibraryFolderObserver.h */,
+                               53BDE19E2D5C8D1C00254560 /* 
VLCMediaLibraryFolderObserver.m */,
                        );
                        path = library;
                        sourceTree = "<group>";
@@ -2361,6 +2366,7 @@
                                7D0F64062202047900FDB91F /* 
VLCLibraryCollectionViewItem.m in Sources */,
                                7D713D322201AE350042BEB7 /* VLCLibraryWindow.m 
in Sources */,
                                7D22A8F422BC14F80063ECD2 /* 
VLCLibrarySortingMenuController.m in Sources */,
+                               53BDE19F2D5C8D1C00254560 /* 
VLCMediaLibraryFolderObserver.m in Sources */,
                                1C3113C91E508C6900D4DD76 /* VLCOutput.m in 
Sources */,
                                535F1BC02B4892A200C78D98 /* 
VLCLibraryHomeViewAudioCarouselContainerView.m in Sources */,
                                7D445D842202524D00263D34 /* VLCPlayQueueItem.m 
in Sources */,


=====================================
modules/gui/macosx/Makefile.am
=====================================
@@ -190,6 +190,8 @@ libmacosx_plugin_la_SOURCES = \
        gui/macosx/library/VLCLibraryWindowTitlesSidebarViewController.m \
        gui/macosx/library/VLCLibraryWindowToolbarDelegate.h \
        gui/macosx/library/VLCLibraryWindowToolbarDelegate.m \
+       gui/macosx/library/VLCMediaLibraryFolderObserver.h \
+       gui/macosx/library/VLCMediaLibraryFolderObserver.m \
        gui/macosx/library/groups-library/VLCLibraryGroupsDataSource.h \
        gui/macosx/library/groups-library/VLCLibraryGroupsDataSource.m \
        gui/macosx/library/groups-library/VLCLibraryGroupsViewController.h \


=====================================
modules/gui/macosx/library/VLCLibraryController.m
=====================================
@@ -30,6 +30,7 @@
 #import "library/VLCInputItem.h"
 #import "library/VLCLibraryModel.h"
 #import "library/VLCLibraryDataTypes.h"
+#import "library/VLCMediaLibraryFolderObserver.h"
 
 #import <vlc_media_library.h>
 
@@ -60,6 +61,10 @@ typedef int (*folder_action_f)(vlc_medialibrary_t*, const 
char*);
                                       selector:@selector(playbackStateChanged:)
                                           name:VLCPlayerStateChanged
                                         object:nil];
+        [defaultNotificationCenter addObserver:self
+                                      
selector:@selector(monitoredFolderChanged:)
+                                          name:VLCMediaLibraryFolderFSEvent
+                                        object:nil];
     }
     return self;
 }
@@ -87,6 +92,12 @@ typedef int (*folder_action_f)(vlc_medialibrary_t*, const 
char*);
     }
 }
 
+- (void)monitoredFolderChanged:(NSNotification *)notification
+{
+    NSURL * const folderURL = (NSURL *)notification.object;
+    [self reloadFolderWithFileURL:folderURL];
+}
+
 - (int)appendItemToPlayQueue:(VLCMediaLibraryMediaItem *)mediaItem 
playImmediately:(BOOL)playImmediately
 {
     if (!_p_libraryInstance) {


=====================================
modules/gui/macosx/library/VLCLibraryModel.m
=====================================
@@ -22,6 +22,8 @@
 
 #import "VLCLibraryModel.h"
 
+#import "VLCMediaLibraryFolderObserver.h"
+
 #import "extensions/NSArray+VLCAdditions.h"
 #import "extensions/NSString+Helpers.h"
 
@@ -94,6 +96,8 @@ NSString * const VLCLibraryModelDiscoveryFailed = 
@"VLCLibraryModelDiscoveryFail
     dispatch_queue_t _groupCacheModificationQueue;
 }
 
+@property (readwrite) NSArray<VLCMediaLibraryFolderObserver *> 
*folderObservers;
+
 @property (readwrite, atomic) NSArray *cachedAudioMedia;
 @property (readwrite, atomic) NSArray *cachedArtists;
 @property (readwrite, atomic) NSArray *cachedAlbums;
@@ -305,6 +309,8 @@ static void libraryCallback(void *p_data, const 
vlc_ml_event_t *p_event)
             self->_initialRecentsCount = 
vlc_ml_count_video_history(self->_p_mediaLibrary, &queryParameters);
             self->_initialRecentAudioCount = 
vlc_ml_count_audio_history(self->_p_mediaLibrary, &queryParameters);
         });
+
+        [self resetCachedListOfMonitoredFolders];
     }
     return self;
 }
@@ -765,18 +771,29 @@ static void libraryCallback(void *p_data, const 
vlc_ml_event_t *p_event)
             return;
         }
 
-        NSMutableArray *mutableArray = [[NSMutableArray alloc] 
initWithCapacity:pp_entrypoints->i_nb_items];
+        NSMutableArray * const mutableArray =
+            [[NSMutableArray alloc] 
initWithCapacity:pp_entrypoints->i_nb_items];
+        NSMutableArray * const mutableObservers =
+            [[NSMutableArray alloc] 
initWithCapacity:pp_entrypoints->i_nb_items];
+
         for (size_t x = 0; x < pp_entrypoints->i_nb_items; x++) {
-            VLCMediaLibraryEntryPoint *entryPoint = 
[[VLCMediaLibraryEntryPoint alloc] 
initWithEntryPoint:&pp_entrypoints->p_items[x]];
+            VLCMediaLibraryEntryPoint * const entryPoint =
+                [[VLCMediaLibraryEntryPoint alloc] 
initWithEntryPoint:&pp_entrypoints->p_items[x]];
             if (entryPoint) {
                 [mutableArray addObject:entryPoint];
+
+                NSURL * const url = [NSURL URLWithString:entryPoint.MRL];
+                VLCMediaLibraryFolderObserver * const observer =
+                    [[VLCMediaLibraryFolderObserver alloc] initWithURL:url];
+                [mutableObservers addObject:observer];
             }
         }
 
         vlc_ml_folder_list_release(pp_entrypoints);
 
         dispatch_async(dispatch_get_main_queue(), ^{
-            self.cachedListOfMonitoredFolders = [mutableArray copy];
+            self.cachedListOfMonitoredFolders = mutableArray.copy;
+            self.folderObservers = mutableObservers.copy;
             [self.changeDelegate 
notifyChange:VLCLibraryModelListOfMonitoredFoldersUpdated withObject:self];
         });
     });


=====================================
modules/gui/macosx/library/VLCMediaLibraryFolderObserver.h
=====================================
@@ -0,0 +1,37 @@
+/*****************************************************************************
+ * VLCMediaLibraryFolderObserver.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 
USA.
+ *****************************************************************************/
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+extern NSString * const VLCMediaLibraryFolderFSEvent;
+
+@interface VLCMediaLibraryFolderObserver : NSObject
+
+@property (readonly) NSURL *url;
+
+- (instancetype)initWithURL:(NSURL *)url;
+
+@end
+
+NS_ASSUME_NONNULL_END


=====================================
modules/gui/macosx/library/VLCMediaLibraryFolderObserver.m
=====================================
@@ -0,0 +1,102 @@
+/*****************************************************************************
+ * VLCMediaLibraryFolderObserver.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 
USA.
+ *****************************************************************************/
+
+#import "VLCMediaLibraryFolderObserver.h"
+
+NSString * const VLCMediaLibraryFolderFSEvent = 
@"VLCMediaLibraryFolderFSEvent";
+NSString * const VLCMediaLibraryFolderFSLastEventIdPrefix = 
@"VLCMediaLibraryFolderFSLastEventId_";
+
+@interface VLCMediaLibraryFolderObserver ()
+
+@property (readonly) FSEventStreamRef stream;
+@property (readonly) CFStringRef urlPathRef;
+@property (readonly) CFArrayRef pathsToWatch;
+@property (readonly) NSString *defaultsKey;
+
+@end
+
+void fsEventCallback(ConstFSEventStreamRef streamRef,
+                     void *clientCallBackInfo,
+                     size_t numEvents,
+                     void *eventPaths,
+                     const FSEventStreamEventFlags eventFlags[],
+                     const FSEventStreamEventId eventIds[])
+{
+    if (numEvents == 0) {
+        return;
+    }
+    
+    VLCMediaLibraryFolderObserver * const observer =
+        (__bridge VLCMediaLibraryFolderObserver *)clientCallBackInfo;
+    NSNumber * const eventId = @(eventIds[0]);
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [NSUserDefaults.standardUserDefaults setObject:eventId 
forKey:observer.defaultsKey];
+        [NSNotificationCenter.defaultCenter 
postNotificationName:VLCMediaLibraryFolderFSEvent
+                                                          object:observer.url];
+    });
+}
+
+@implementation VLCMediaLibraryFolderObserver
+
+- (instancetype)initWithURL:(NSURL *)url
+{
+    self = [super init];
+    if (self) {
+        _url = url;
+        _urlPathRef = (__bridge_retained CFStringRef)url.path;
+        _pathsToWatch = CFArrayCreate(NULL, (const void **)&_urlPathRef, 1, 
NULL);
+        _defaultsKey =
+            [NSString stringWithFormat:@"%@%@", 
VLCMediaLibraryFolderFSLastEventIdPrefix, url.path];
+
+        FSEventStreamContext context = { 0, (__bridge void *)self, NULL, NULL, 
NULL };
+        const FSEventStreamCreateFlags createFlags =
+            kFSEventStreamCreateFlagUseCFTypes | 
kFSEventStreamCreateFlagIgnoreSelf;
+
+        NSNumber * const lastEventIdDefaults =
+            (NSNumber *)[NSUserDefaults.standardUserDefaults 
objectForKey:self.defaultsKey];
+        const FSEventStreamEventId lastEventId = lastEventIdDefaults == nil
+            ? kFSEventStreamEventIdSinceNow
+            : lastEventIdDefaults.unsignedLongLongValue;
+
+        _stream = FSEventStreamCreate(kCFAllocatorDefault,
+                                      &fsEventCallback,
+                                      &context,
+                                      _pathsToWatch,
+                                      lastEventId,
+                                      3.0,
+                                      createFlags);
+
+        FSEventStreamSetDispatchQueue(_stream, 
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));
+        NSAssert(FSEventStreamStart(_stream), @"FSEvent stream should be 
started for %@", url.path);
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    FSEventStreamStop(_stream);
+    FSEventStreamRelease(_stream);
+    CFRelease(_urlPathRef);
+    CFRelease(_pathsToWatch);
+}
+
+@end


=====================================
modules/gui/macosx/views/VLCStatusNotifierView.m
=====================================
@@ -108,6 +108,10 @@ NSString * const VLCMessageTimeoutTimerUserInfoMessageKey 
= @"VLCMessageTimeoutT
 
 - (void)removeMessage:(NSString *)message
 {
+    if (message == nil) {
+        return;
+    }
+
     const NSInteger matchingIndex = [self.messages 
indexOfObjectPassingTest:^BOOL(NSString * const string, NSUInteger, BOOL *){
         return [string hasPrefix:message];
     }];



View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/3f9d7ff7d86fce6ba509a2310f2c0695808b7b67...b3f9613ca56f97e3f0092f6e1c923872696e1c2c

-- 
View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/3f9d7ff7d86fce6ba509a2310f2c0695808b7b67...b3f9613ca56f97e3f0092f6e1c923872696e1c2c
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance
_______________________________________________
vlc-commits mailing list
[email protected]
https://mailman.videolan.org/listinfo/vlc-commits

Reply via email to