[vlc-commits] [Git][videolan/vlc][master] 4 commits: macosx: Add ability for navigation state and stack to keep track of currently-viewed media source

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Fri Nov 18 19:37:32 UTC 2022



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


Commits:
85132c6a by Claudio Cambra at 2022-11-18T19:08:13+00:00
macosx: Add ability for navigation state and stack to keep track of currently-viewed media source

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

- - - - -
0f069e25 by Claudio Cambra at 2022-11-18T19:08:13+00:00
macosx: Record navigation state when moving through stream/filesystem hierarchy in mediasource views

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

- - - - -
6619da94 by Claudio Cambra at 2022-11-18T19:08:13+00:00
macosx: Fix crashing when going forward in the navstack, improve safety of codepaths

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

- - - - -
0204a5f3 by Claudio Cambra at 2022-11-18T19:08:13+00:00
macosx: Prevent double-storing of navigation state when opening media source view

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

- - - - -


9 changed files:

- modules/gui/macosx/library/VLCInputItem.m
- modules/gui/macosx/library/VLCLibraryNavigationStack.m
- modules/gui/macosx/library/VLCLibraryNavigationState.h
- modules/gui/macosx/library/VLCLibraryNavigationState.m
- modules/gui/macosx/media-source/VLCMediaSource.h
- modules/gui/macosx/media-source/VLCMediaSource.m
- modules/gui/macosx/media-source/VLCMediaSourceBaseDataSource.h
- modules/gui/macosx/media-source/VLCMediaSourceBaseDataSource.m
- modules/gui/macosx/media-source/VLCMediaSourceDataSource.m


Changes:

=====================================
modules/gui/macosx/library/VLCInputItem.m
=====================================
@@ -581,6 +581,10 @@ static const struct input_preparser_callbacks_t preparseCallbacks = {
     self = [super init];
     if (self && p_inputNode != NULL) {
         _vlcInputItemNode = p_inputNode;
+        
+        if (_vlcInputItemNode->p_item) {
+            _inputItem = [[VLCInputItem alloc] initWithInputItem:_vlcInputItemNode->p_item];
+        }
     }
     return self;
 }
@@ -595,14 +599,6 @@ static const struct input_preparser_callbacks_t preparseCallbacks = {
     return [NSString stringWithFormat:@"%@: node: %p input name: %@, number of children: %i", NSStringFromClass([self class]),_vlcInputItemNode, inputItemName, self.numberOfChildren];
 }
 
-- (VLCInputItem *)inputItem
-{
-    if (_vlcInputItemNode->p_item) {
-        return [[VLCInputItem alloc] initWithInputItem:_vlcInputItemNode->p_item];
-    }
-    return nil;
-}
-
 - (int)numberOfChildren
 {
     return _vlcInputItemNode->i_children;


=====================================
modules/gui/macosx/library/VLCLibraryNavigationStack.m
=====================================
@@ -25,7 +25,10 @@
 #import "VLCLibraryWindow.h"
 #import "VLCLibraryAudioDataSource.h"
 #import "VLCLibraryNavigationState.h"
+#import "VLCInputItem.h"
 #import "media-source/VLCMediaSourceBaseDataSource.h"
+#import "media-source/VLCMediaSourceDataSource.h"
+#import "media-source/VLCMediaSource.h"
 
 @interface VLCLibraryNavigationCurrentStackPosition : NSObject
 
@@ -126,6 +129,7 @@
         NSUInteger firstIndexToRemove = _currentPosition.navigationStackIndex + 1;
         // -1 to account for the array count
         NSRange rangeToRemove = NSMakeRange(firstIndexToRemove, (_navigationStates.count - 1) - _currentPosition.navigationStackIndex);
+        [self removeAndCleanUpStatesInRange:rangeToRemove];
         [_navigationStates removeObjectsInRange:rangeToRemove];
     }
 
@@ -136,6 +140,22 @@
     [self updateDelegateNavigationButtons];
 }
 
+- (void)removeAndCleanUpStatesInRange:(NSRange)range
+{
+    NSAssert(range.location + range.length - 1 < _navigationStates.count, @"Invalid range for state removal and cleanup, out of bounds.");
+    
+    for (NSUInteger i = range.location; i < range.length; ++i) {
+        VLCLibraryNavigationState *state = [_navigationStates objectAtIndex:i];
+        VLCInputNode *stateNode = state.currentNodeDisplayed;
+        
+        if (stateNode) {
+            [state.currentMediaSource.displayedMediaSource clearChildNodesForNode:stateNode.vlcInputItemNode];
+        }
+        
+        [_navigationStates removeObjectAtIndex:i];
+    }
+}
+
 - (void)updateDelegateNavigationButtons
 {
     if(_delegate == nil) {
@@ -155,6 +175,8 @@
     [_delegate.segmentedTitleControl setSelectedSegment:state.libraryWindowSelectedSegment];
     [_delegate.audioSegmentedControl setSelectedSegment:state.audioLibraryViewSelectedSegment];
     [_delegate.gridVsListSegmentedControl setSelectedSegment:state.viewModeSelectedSegment];
+    [_delegate.mediaSourceDataSource setChildDataSource:state.currentMediaSource];
+    [_delegate.mediaSourceDataSource.childDataSource setNodeToDisplay:state.currentNodeDisplayed];
 
     [_delegate segmentedControlAction:self];
     [_delegate.libraryAudioDataSource segmentedControlAction:self];


=====================================
modules/gui/macosx/library/VLCLibraryNavigationState.h
=====================================
@@ -3,7 +3,7 @@
  *****************************************************************************
  * Copyright (C) 2022 VLC authors and VideoLAN
  *
- * Authors: Claudio Cambra <claudio.cambra at gmail.com>
+ * 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
@@ -26,15 +26,19 @@ NS_ASSUME_NONNULL_BEGIN
 
 @class VLCLibraryWindow;
 @class VLCMediaSourceDataSource;
+ at class VLCInputNode;
+ at class VLCMediaSource;
 
 @interface VLCLibraryNavigationState : NSObject
 
 @property (readonly) NSInteger libraryWindowSelectedSegment;
 @property (readonly) NSInteger viewModeSelectedSegment;
 @property (readonly) NSInteger audioLibraryViewSelectedSegment;
+ at property (readonly) VLCMediaSourceDataSource *currentMediaSource;
+ at property (readonly) VLCInputNode *currentNodeDisplayed;
 
 - (instancetype)initFromLibraryWindow:(VLCLibraryWindow *)libraryWindow;
 
 @end
 
-NS_ASSUME_NONNULL_END
\ No newline at end of file
+NS_ASSUME_NONNULL_END


=====================================
modules/gui/macosx/library/VLCLibraryNavigationState.m
=====================================
@@ -23,6 +23,8 @@
 #import "VLCLibraryNavigationState.h"
 
 #import "VLCLibraryWindow.h"
+#import "media-source/VLCMediaSourceBaseDataSource.h"
+#import "media-source/VLCMediaSourceDataSource.h"
 
 @implementation VLCLibraryNavigationState
 
@@ -34,6 +36,8 @@
         _libraryWindowSelectedSegment = libraryWindow.segmentedTitleControl.selectedSegment;
         _viewModeSelectedSegment = libraryWindow.gridVsListSegmentedControl.selectedSegment;
         _audioLibraryViewSelectedSegment = libraryWindow.audioSegmentedControl.selectedSegment;
+        _currentMediaSource = libraryWindow.mediaSourceDataSource.childDataSource;
+        _currentNodeDisplayed = libraryWindow.mediaSourceDataSource.childDataSource.nodeToDisplay;
     }
 
     return navState;


=====================================
modules/gui/macosx/media-source/VLCMediaSource.h
=====================================
@@ -42,6 +42,7 @@ extern NSString *VLCMediaSourcePreparsingEnded;
                         forCategory:(enum services_discovery_category_e)category;
 
 - (void)preparseInputNodeWithinTree:(VLCInputNode *)inputNode;
+- (void)clearChildNodesForNode:(input_item_node_t*)inputNode;
 
 @property (nonatomic, readonly) NSString *mediaSourceDescription;
 @property (nonatomic, readonly) VLCInputNode *rootNode;


=====================================
modules/gui/macosx/media-source/VLCMediaSource.m
=====================================
@@ -180,6 +180,11 @@ static const char *const localDevicesDescription = "My Machine";
 
 - (void)preparseInputNodeWithinTree:(VLCInputNode *)inputNode
 {
+    if(!inputNode) {
+        NSLog(@"Could not preparese input node, is null.");
+        return;
+    }
+
     if (_p_mediaSource->description == localDevicesDescription) {
         [self generateLocalDevicesTree];
     }
@@ -189,24 +194,24 @@ static const char *const localDevicesDescription = "My Machine";
     }
 
     if (inputNode.inputItem.inputType == ITEM_TYPE_DIRECTORY) {
-	input_item_node_t *vlcInputNode = inputNode.vlcInputItemNode;
-
-	[self clearChildNodesForNode:vlcInputNode];
+        input_item_node_t *vlcInputNode = inputNode.vlcInputItemNode;
         NSURL *dirUrl = [NSURL URLWithString:inputNode.inputItem.MRL];
-	[self generateChildNodesForDirectoryNode:vlcInputNode withUrl:dirUrl];
 
-	return;
+        [self generateChildNodesForDirectoryNode:vlcInputNode withUrl:dirUrl];
+        return;
     }
 
     vlc_media_tree_Preparse(_p_mediaSource->tree, _p_libvlcInstance, inputNode.inputItem.vlcInputItem, NULL);
 }
 
-- (void)clearChildNodesForNode:(input_item_node_t*)inputNode
+- (void)clearChildNodesForNode:(nonnull input_item_node_t*)inputNode
 {
+    NSAssert(inputNode != NULL, @"Could not clear child nodes for input node as node is null");
+
     while(inputNode->i_children > 0) {
-	input_item_node_t *childNode = inputNode->pp_children[0];
-	input_item_node_RemoveNode(inputNode, childNode);
-	input_item_node_Delete(childNode);
+        input_item_node_t *childNode = inputNode->pp_children[0];
+        input_item_node_RemoveNode(inputNode, childNode);
+        input_item_node_Delete(childNode);
     }
 }
 


=====================================
modules/gui/macosx/media-source/VLCMediaSourceBaseDataSource.h
=====================================
@@ -40,7 +40,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (readwrite) NSButton *homeButton;
 @property (readwrite) NSPathControl *pathControl;
 @property (readwrite, nonatomic) VLCMediaSourceMode mediaSourceMode;
- at property (readonly) VLCMediaSourceDataSource *childDataSource;
+ at property (readwrite, nonatomic) VLCMediaSourceDataSource *childDataSource;
 
 - (void)setupViews;
 - (void)reloadViews;


=====================================
modules/gui/macosx/media-source/VLCMediaSourceBaseDataSource.m
=====================================
@@ -241,9 +241,9 @@ NSString *VLCMediaSourceTableViewCellIdentifier = @"VLCMediaSourceTableViewCellI
     }
 
     [self configureChildDataSourceWithNode:childNode andMediaSource:mediaSource];
-
     [self reloadData];
 }
+
 - (NSView *)collectionView:(NSCollectionView *)collectionView
 viewForSupplementaryElementOfKind:(NSCollectionViewSupplementaryElementKind)kind
                atIndexPath:(NSIndexPath *)indexPath
@@ -357,17 +357,40 @@ referenceSizeForHeaderInSection:(NSInteger)section
 
 - (void)configureChildDataSourceWithNode:(VLCInputNode *)node andMediaSource:(VLCMediaSource *)mediaSource
 {
-    _childDataSource = [[VLCMediaSourceDataSource alloc] init];
+    if (!node || !mediaSource) {
+        NSLog(@"Received bad node or media source, could not configure child data media source");
+        return;
+    }
+    
+    VLCMediaSourceDataSource *newChildDataSource = [[VLCMediaSourceDataSource alloc] init];
+    
+    newChildDataSource.displayedMediaSource = mediaSource;
+    newChildDataSource.nodeToDisplay = node;
+    newChildDataSource.collectionView = self.collectionView;
+    newChildDataSource.pathControl = self.pathControl;
+    newChildDataSource.tableView = self.tableView;
+    
+    [self setChildDataSource:newChildDataSource];
+    [[VLCMain sharedInstance].libraryWindow.navigationStack appendCurrentLibraryState];
+}
 
-    VLCInputItem *nodeInput = node.inputItem;
+- (void)setChildDataSource:(VLCMediaSourceDataSource *)childDataSource
+{
+    if (!childDataSource) {
+        NSLog(@"Received bad childDataSource, returning home");
+        [self returnHome];
+        return;
+    } else if (childDataSource == _childDataSource) {
+        NSLog(@"Received same childDataSource");
+        return;
+    }
+    
+    _childDataSource = childDataSource;
+    
+    VLCInputItem *nodeInput = childDataSource.nodeToDisplay.inputItem;
     self.pathControl.URL = [NSURL URLWithString:[NSString stringWithFormat:@"vlc://%@", [nodeInput.name stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]]];
     self.pathControl.hidden = NO;
     
-    _childDataSource.displayedMediaSource = mediaSource;
-    _childDataSource.nodeToDisplay = node;
-    _childDataSource.collectionView = self.collectionView;
-    _childDataSource.pathControl = self.pathControl;
-    _childDataSource.tableView = self.tableView;
     [_childDataSource setupViews];
 
     self.collectionView.dataSource = _childDataSource;
@@ -379,7 +402,7 @@ referenceSizeForHeaderInSection:(NSInteger)section
 
 #pragma mark - user interaction with generic buttons
 
-- (void)homeButtonAction:(id)sender
+- (void)returnHome
 {
     self.collectionView.dataSource = self;
     self.collectionView.delegate = self;
@@ -391,6 +414,15 @@ referenceSizeForHeaderInSection:(NSInteger)section
     [self reloadData];
 }
 
+- (void)homeButtonAction:(id)sender
+{
+    [self returnHome];
+    VLCLibraryNavigationStack *mainNavStack = [VLCMain sharedInstance].libraryWindow.navigationStack;
+    if(sender != mainNavStack && sender != self) {
+        [[[[VLCMain sharedInstance] libraryWindow] navigationStack] appendCurrentLibraryState];
+    }
+}
+
 - (void)setCurrentViewMode
 {
     if (_gridViewMode) {


=====================================
modules/gui/macosx/media-source/VLCMediaSourceDataSource.m
=====================================
@@ -23,6 +23,8 @@
 #import "VLCMediaSourceDataSource.h"
 
 #import "library/VLCInputItem.h"
+#import "library/VLCLibraryWindow.h"
+#import "library/VLCLibraryNavigationStack.h"
 #import "library/VLCLibraryTableCellView.h"
 #import "media-source/VLCMediaSourceCollectionViewItem.h"
 #import "media-source/VLCMediaSource.h"
@@ -39,8 +41,10 @@
 
 @implementation VLCMediaSourceDataSource
 
-- (void)setNodeToDisplay:(VLCInputNode *)nodeToDisplay
+- (void)setNodeToDisplay:(nonnull VLCInputNode*)nodeToDisplay
 {
+    NSAssert(nodeToDisplay, @"Nil node to display, will not set");
+    
     _nodeToDisplay = nodeToDisplay;
     [self.displayedMediaSource preparseInputNodeWithinTree:_nodeToDisplay];
 }
@@ -166,6 +170,7 @@
         self.pathControl.URL = [NSURL URLWithString:[self.pathControl.URL.path stringByAppendingPathComponent:[childRootInput.name stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]]];
         self.nodeToDisplay = node;
         [self reloadData];
+        [[VLCMain sharedInstance].libraryWindow.navigationStack appendCurrentLibraryState];
     } else if (childRootInput.inputType == ITEM_TYPE_FILE && allowPlayback) {
         [[[VLCMain sharedInstance] playlistController] addInputItem:childRootInput.vlcInputItem atPosition:-1 startPlayback:YES];
     }



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/6f996ffa27a620e1a25cffc2039a322eb4fdabc2...0204a5f3cba76a164d7672b8d49f06274d8cdcfb

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/6f996ffa27a620e1a25cffc2039a322eb4fdabc2...0204a5f3cba76a164d7672b8d49f06274d8cdcfb
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