[vlc-commits] [Git][videolan/vlc][master] 12 commits: macosx: Add starter VLCMediaLibraryFolderObserver
Felix Paul Kühne (@fkuehne)
gitlab at videolan.org
Fri Feb 14 05:47:03 UTC 2025
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 <developer at claudiocambra.com>
- - - - -
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 <developer at claudiocambra.com>
- - - - -
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 <developer at claudiocambra.com>
- - - - -
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 <developer at claudiocambra.com>
- - - - -
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 <developer at claudiocambra.com>
- - - - -
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 <developer at claudiocambra.com>
- - - - -
0e9077fd by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Refresh observers on monitored folders refresh
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
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 <developer at claudiocambra.com>
- - - - -
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 <developer at claudiocambra.com>
- - - - -
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 <developer at claudiocambra.com>
- - - - -
b33b59d4 by Claudio Cambra at 2025-02-14T05:23:26+00:00
macosx: Fix warning regarding const fs context
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
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 <developer at claudiocambra.com>
- - - - -
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;
}
+ at 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 <developer at claudiocambra.com>
+ *
+ * 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;
+
+ at interface VLCMediaLibraryFolderObserver : NSObject
+
+ at property (readonly) NSURL *url;
+
+- (instancetype)initWithURL:(NSURL *)url;
+
+ at 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 <developer at claudiocambra.com>
+ *
+ * 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_";
+
+ at interface VLCMediaLibraryFolderObserver ()
+
+ at property (readonly) FSEventStreamRef stream;
+ at property (readonly) CFStringRef urlPathRef;
+ at property (readonly) CFArrayRef pathsToWatch;
+ at property (readonly) NSString *defaultsKey;
+
+ at 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];
+ });
+}
+
+ at 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);
+}
+
+ at 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
More information about the vlc-commits
mailing list