[vlc-commits] [Git][videolan/vlc][master] 32 commits: macosx: Do not update item in information window when currently playing item changes

Steve Lhomme (@robUx4) gitlab at videolan.org
Mon Jul 8 11:57:23 UTC 2024



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
8e9fbb33 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Do not update item in information window when currently playing item changes

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

- - - - -
0f3c156e by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Do not update statistics at all when statistics are disabled

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

- - - - -
ef3938b2 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: More strictly handle conditions under which statistics should be updated

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

- - - - -
5bced44b by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Verify we are not updating statistics for the wrong item

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

- - - - -
3d8c217b by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Use direct representedInputItems setter to handle changes after setting this property

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

- - - - -
b63600fc by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Add missing "title" macro action for inputItem PERFORM_ACTION_PER_INPUTITEM_NSSTRING_PROP

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

- - - - -
90fdab4e by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Include differing fields in commonInputItemData

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

- - - - -
a3681919 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Add MRL and decoded MRL data to inputItem PERFORM_ACTION_PER_INPUTITEM_NSSTRING_PROP

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

- - - - -
a2a455c5 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Display differing field values with a placeholder string in information window

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

- - - - -
8c8eb5b0 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Do not use magic string for differing values in input item common data dict

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

- - - - -
f5bc991b by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Fix incorrect comment regarding information window text fields and input item properties

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

- - - - -
c82f65ae by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: When pressing copy in information window with multiple input items, present a menu to pick which item to copy the MRL for

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

- - - - -
f3fa3e75 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Improve positioning of the menu for copying MRL

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

- - - - -
5e16b6d2 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Handle information window artwork setting in setter for represented items

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

- - - - -
9305b7e5 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Add setter for multiple VLCLibraryRepresentedItems in VLCInformationWindowController

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

- - - - -
fee7e424 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Simplify setting of library items on information window controller, support multiple items

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

- - - - -
3fc10d3c by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Fix artwork fetching for library items in information window controller

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

- - - - -
b71e5eee by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Check if each represented item belongs to the same album

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

- - - - -
eba12b66 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Add class method to directly get cached small artwork from image cache

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

- - - - -
a1dbb652 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Make composite image generation more flexible regarding item count

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

- - - - -
027d3110 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Generate compound image from artwork MRLs of selected represented items in information window controller

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

- - - - -
6011d553 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Ensure composite image set on artwork button in information window is not of size {0, 0}

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

- - - - -
9f1625bf by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Check for the artwork mrls of represented library item's media items in information window artwork button presentation

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

- - - - -
3d3cb68f by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Provide a fallback nsimage from image cache if image not in cache

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

- - - - -
de90834e by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Make copy mrl menu title translatable

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

- - - - -
7941c7c7 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Handle fetching of artwork for information window via library image cache

This way we can ensure the thumbnails will be generated for library items if they have not been already

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

- - - - -
2e6cb3fe by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Synchronise concurrent access to artwork mrl set and artwork array

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

- - - - -
9d29c035 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Remove unused setRepresentedMediaLibraryAudioGroup

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

- - - - -
b6105397 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Remove setRepresentedInputItem from information window controller, just use array

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

- - - - -
df5dc711 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Create artwork for all of the input items set on information window controller

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

- - - - -
314e45a2 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Fix crash from non-main-queue window creation in information window controller

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

- - - - -
438a5675 by Claudio Cambra at 2024-07-08T11:41:01+00:00
macosx: Fix multiple-selection information window handling in playlist table view

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

- - - - -


10 changed files:

- modules/gui/macosx/extensions/NSImage+VLCAdditions.m
- modules/gui/macosx/library/VLCInputItem.h
- modules/gui/macosx/library/VLCInputItem.m
- modules/gui/macosx/library/VLCLibraryImageCache.h
- modules/gui/macosx/library/VLCLibraryImageCache.m
- modules/gui/macosx/library/VLCLibraryMenuController.m
- modules/gui/macosx/menus/VLCMainMenu.m
- modules/gui/macosx/panels/VLCInformationWindowController.h
- modules/gui/macosx/panels/VLCInformationWindowController.m
- modules/gui/macosx/playlist/VLCPlaylistMenuController.m


Changes:

=====================================
modules/gui/macosx/extensions/NSImage+VLCAdditions.m
=====================================
@@ -161,9 +161,8 @@
                                                                size:(const NSSize)size
                                                       gridItemCount:(const NSUInteger)gridItemCount
 {
-    const float sqrtAxisItemCount = sqrt(gridItemCount);
+    const float sqrtAxisItemCount = ceil(sqrt(gridItemCount));
     const float roundAxisItemCount = roundf(sqrtAxisItemCount);
-    NSAssert(sqrtAxisItemCount == roundAxisItemCount, @"Provided grid item count should be an integer square root");
 
     // Default to just one item if there are not enough images
     const NSUInteger actualGridItemCount = images.count >= gridItemCount ? gridItemCount : 1;


=====================================
modules/gui/macosx/library/VLCInputItem.h
=====================================
@@ -37,6 +37,7 @@ extern NSString *VLCInputItemPreparsingSkipped;
 extern NSString *VLCInputItemPreparsingFailed;
 extern NSString *VLCInputItemPreparsingTimeOut;
 extern NSString *VLCInputItemPreparsingSucceeded;
+extern NSString * const VLCInputItemCommonDataDifferingFlagString;
 
 @interface VLCInputItem : NSObject<VLCLocallyManipulableItemProtocol>
 


=====================================
modules/gui/macosx/library/VLCInputItem.m
=====================================
@@ -38,6 +38,7 @@ NSString *VLCInputItemPreparsingSkipped = @"VLCInputItemPreparsingSkipped";
 NSString *VLCInputItemPreparsingFailed = @"VLCInputItemPreparsingFailed";
 NSString *VLCInputItemPreparsingTimeOut = @"VLCInputItemPreparsingTimeOut";
 NSString *VLCInputItemPreparsingSucceeded = @"VLCInputItemPreparsingSucceeded";
+NSString * const VLCInputItemCommonDataDifferingFlagString = @"<differing>";
 
 @interface VLCInputItem()
 {
@@ -137,6 +138,7 @@ static const struct vlc_metadata_cbs preparseCallbacks = {
     FREENULL(psz_title);
     return returnValue;
 }
+
 -(void)setTitle:(NSString *)title
 {
     if (_vlcInputItem) {
@@ -701,6 +703,9 @@ NSDictionary<NSString *, id> * const commonInputItemData(NSArray<VLCInputItem *>
     NSMutableDictionary<NSString *, id> *const commonData = [[NSMutableDictionary alloc] init];
 
 #define PERFORM_ACTION_PER_INPUTITEM_NSSTRING_PROP(action)                                  \
+action(MRL);                                                                                \
+action(decodedMRL);                                                                         \
+action(title);                                                                              \
 action(artist);                                                                             \
 action(album);                                                                              \
 action(trackNumber);                                                                        \
@@ -728,13 +733,14 @@ BOOL differing_##prop = NO;
 #define CREATE_PROP_VAR(prop)                                                               \
 NSString * const firstItem_##prop = firstInputItem.prop;
 
-#define SET_IF_DIFFERING(prop)                                                              \
+#define UPDATE_IF_DIFFERING_BOOL(prop)                                                          \
 differing_##prop = differing_##prop || ![inputItem.prop isEqualToString:firstItem_##prop];
 
-#define ADD_PROP_TO_DICT_IF_DIFFERING(prop)                                                 \
-if (!differing_##prop && firstItem_##prop != nil) {                                         \
-    [commonData setObject:firstItem_##prop forKey:[NSString stringWithUTF8String:#prop]];   \
-}
+#define ADD_PROP_TO_DICT(prop)                                                              \
+NSString * firstItemValue_##prop = firstItem_##prop == nil ? @"" : firstItem_##prop;        \
+NSString * const value_##prop =                                                             \
+    differing_##prop ? VLCInputItemCommonDataDifferingFlagString : firstItemValue_##prop;   \
+[commonData setObject:value_##prop forKey:[NSString stringWithUTF8String:#prop]];           \
 
     PERFORM_ACTION_PER_INPUTITEM_PROP(CREATE_DIFFER_BOOL);
     PERFORM_ACTION_PER_INPUTITEM_NSSTRING_PROP(CREATE_PROP_VAR);
@@ -745,11 +751,11 @@ if (!differing_##prop && firstItem_##prop != nil) {
     for (uint i = 1; i < inputItems.count; ++i) {
         VLCInputItem * const inputItem = inputItems[i];
 
-        PERFORM_ACTION_PER_INPUTITEM_NSSTRING_PROP(SET_IF_DIFFERING);
+        PERFORM_ACTION_PER_INPUTITEM_NSSTRING_PROP(UPDATE_IF_DIFFERING_BOOL);
         differing_artworkURL = differing_artworkURL || ![inputItem.artworkURL.absoluteString isEqualToString:firstItem_artworkURL.absoluteString];
     }
 
-    PERFORM_ACTION_PER_INPUTITEM_PROP(ADD_PROP_TO_DICT_IF_DIFFERING);
+    PERFORM_ACTION_PER_INPUTITEM_PROP(ADD_PROP_TO_DICT);
 
 #undef PERFORM_ACTION_PER_INPUTITEM_PROP
 #undef CREATE_DIFFER_BOOL


=====================================
modules/gui/macosx/library/VLCLibraryImageCache.h
=====================================
@@ -36,6 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
                withCompletion:(void(^)(const NSImage *))completionHandler;
 + (void)thumbnailForPlaylistItem:(VLCPlaylistItem *)playlistItem
                   withCompletion:(void(^)(const NSImage *))completionHandler;
++ (NSImage *)thumbnailAtMrl:(NSString *)smallArtworkMRL;
 
 @end
 


=====================================
modules/gui/macosx/library/VLCLibraryImageCache.m
=====================================
@@ -208,4 +208,12 @@ const NSUInteger kVLCCompositeImageDefaultCompositedGridItemCount = 4;
     }
 }
 
++ (NSImage *)thumbnailAtMrl:(NSString *)smallArtworkMRL
+{
+    NSImage * const cachedImage = 
+        [VLCLibraryImageCache.sharedImageCache->_imageCache objectForKey:smallArtworkMRL];
+    return cachedImage ?
+        cachedImage : [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:smallArtworkMRL]];
+}
+
 @end


=====================================
modules/gui/macosx/library/VLCLibraryMenuController.m
=====================================
@@ -225,15 +225,10 @@
         _informationWindowController = [[VLCInformationWindowController alloc] init];
     }
 
-    const id<VLCMediaLibraryItemProtocol> actualItem = self.representedItems.firstObject.item;
-    if (actualItem != nil) {
-        if ([actualItem isKindOfClass:VLCAbstractMediaLibraryAudioGroup.class]) {
-            [_informationWindowController setRepresentedMediaLibraryAudioGroup:(VLCAbstractMediaLibraryAudioGroup *)actualItem];
-        } else {
-            [_informationWindowController setRepresentedInputItem:actualItem.firstMediaItem.inputItem];
-        }
+    if (self.representedItems != nil && self.representedItems.count > 0) {
+        [_informationWindowController setRepresentedMediaLibraryItems:self.representedItems];
     } else if (self.representedInputItems != nil && self.representedInputItems.count > 0) {
-        _informationWindowController.representedInputItem = self.representedInputItems.firstObject;
+        _informationWindowController.representedInputItems = self.representedInputItems;
     }
 
     [_informationWindowController toggleWindow:sender];


=====================================
modules/gui/macosx/menus/VLCMainMenu.m
=====================================
@@ -1538,7 +1538,7 @@ typedef NS_ENUM(NSInteger, VLCObjectType) {
         _infoWindowController.mainMenuInstance = YES;
     }
 
-    _infoWindowController.representedInputItem = _playlistController.currentlyPlayingInputItem;
+    _infoWindowController.representedInputItems = @[_playlistController.currentlyPlayingInputItem];
     [_infoWindowController toggleWindow:sender];
 }
 


=====================================
modules/gui/macosx/panels/VLCInformationWindowController.h
=====================================
@@ -25,6 +25,7 @@
 
 @class VLCInputItem;
 @class VLCImageView;
+ at class VLCLibraryRepresentedItem;
 @class VLCSettingTextField;
 @protocol VLCMediaLibraryAudioGroupProtocol;
 
@@ -109,7 +110,7 @@
 @property (readwrite, weak) IBOutlet NSTextField *demuxDiscontinuitiesLabel;
 @property (readwrite, weak) IBOutlet NSTextField *demuxDiscontinuitiesTextField;
 
- at property (readwrite, strong, atomic) NSArray<VLCInputItem *> *representedInputItems;
+ at property (readwrite, strong, nonatomic) NSArray<VLCInputItem *> *representedInputItems;
 @property (readwrite) BOOL mainMenuInstance;
 
 - (IBAction)toggleWindow:(id)sender;
@@ -117,7 +118,6 @@
 - (IBAction)saveMetaData:(id)sender;
 - (IBAction)chooseArtwork:(id)sender;
 
-- (void)setRepresentedInputItem:(VLCInputItem *)representedInputItem;
-- (void)setRepresentedMediaLibraryAudioGroup:(id<VLCMediaLibraryAudioGroupProtocol>)representedMediaLibraryAudioGroup;
+- (void)setRepresentedMediaLibraryItems:(NSArray<VLCLibraryRepresentedItem *> *)representedMediaLibraryItems;
 
 @end


=====================================
modules/gui/macosx/panels/VLCInformationWindowController.m
=====================================
@@ -23,12 +23,14 @@
 
 #import "VLCInformationWindowController.h"
 
+#import "extensions/NSImage+VLCAdditions.h"
 #import "extensions/NSString+Helpers.h"
 
 #import "library/VLCInputItem.h"
 #import "library/VLCLibraryController.h"
 #import "library/VLCLibraryImageCache.h"
 #import "library/VLCLibraryModel.h"
+#import "library/VLCLibraryRepresentedItem.h"
 
 #import "main/VLCMain.h"
 
@@ -110,18 +112,16 @@ actionCallback(encodedBy);
 
 - (void)awakeFromNib
 {
+    _statisticsEnabled = var_InheritBool(getIntf(), "stats");
+
     [self.window setExcludedFromWindowsMenu: YES];
     [self.window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
     [self.window setInitialFirstResponder: _decodedMRLLabel];
 
-    _outlineView.dataSource = self;
+    self.outlineView.dataSource = self;
 
-    NSNotificationCenter *notificationCenter = NSNotificationCenter.defaultCenter;
-    if (_mainMenuInstance) {
-        [notificationCenter addObserver:self
-                               selector:@selector(currentPlayingItemChanged:)
-                                   name:VLCPlayerCurrentMediaItemChanged
-                                 object:nil];
+    NSNotificationCenter * const notificationCenter = NSNotificationCenter.defaultCenter;
+    if (_mainMenuInstance && _statisticsEnabled) {
         [notificationCenter addObserver:self
                                selector:@selector(updateStatistics:)
                                    name:VLCPlayerStatisticsUpdated
@@ -140,11 +140,8 @@ actionCallback(encodedBy);
                                name:VLCInputItemPreparsingSucceeded
                              object:nil];
 
-    [notificationCenter postNotificationName:VLCPlayerStatisticsUpdated object:self];
-
     [self initStrings];
 
-    _statisticsEnabled = var_InheritBool(getIntf(), "stats");
     if (!_statisticsEnabled || !_mainMenuInstance) {
         if ([_segmentedView segmentCount] >= 3)
             [_segmentedView setSegmentCount: 2];
@@ -233,9 +230,44 @@ _##field##TextField.delegate = self
 
 - (IBAction)copyMrl:(id)sender
 {
+    if (self.representedInputItems.count == 0) {
+        return;
+    } else if (self.representedInputItems.count == 1) {
+        NSPasteboard * const pasteboard = NSPasteboard.generalPasteboard;
+        [pasteboard clearContents];
+        [pasteboard setString:self.representedInputItems.firstObject.MRL
+                      forType:NSPasteboardTypeString];
+    } else {
+        NSMenu * const choiceMenu = [[NSMenu alloc] initWithTitle:_NS("Copy MRL")];
+        for (VLCInputItem * const inputItem in self.representedInputItems) {
+            NSMenuItem * const menuItem =
+                [[NSMenuItem alloc] initWithTitle:inputItem.title
+                                           action:@selector(copyMrlFromMenuItem:)
+                                    keyEquivalent:@""];
+            menuItem.representedObject = inputItem;
+            [choiceMenu addItem:menuItem];
+        }
+        CGFloat senderHeight = 0;
+        if ([sender isKindOfClass:NSView.class]) {
+            senderHeight = ((NSView *)sender).frame.size.height;
+        }
+        [choiceMenu popUpMenuPositioningItem:nil
+                                  atLocation:NSMakePoint(0, senderHeight)
+                                      inView:sender];
+    }
+}
+
+- (void)copyMrlFromMenuItem:(id)sender
+{
+    NSParameterAssert(sender);
+    NSParameterAssert([sender isKindOfClass:NSMenuItem.class]);
+    NSMenuItem * const menuItem = (NSMenuItem *)sender;
+    NSParameterAssert(menuItem.representedObject);
+    NSParameterAssert([menuItem.representedObject isKindOfClass:VLCInputItem.class]);
+    VLCInputItem * const inputItem = (VLCInputItem *)menuItem.representedObject;
     NSPasteboard * const pasteboard = NSPasteboard.generalPasteboard;
     [pasteboard clearContents];
-    [pasteboard setString:self.representedInputItems.firstObject.MRL forType:NSPasteboardTypeString];
+    [pasteboard setString:inputItem.MRL forType:NSPasteboardTypeString];
 }
 
 - (void)initMediaPanelStats
@@ -262,40 +294,124 @@ _##field##TextField.delegate = self
     [_lostAudioBuffersTextField setIntValue: 0];
 }
 
-- (void)currentPlayingItemChanged:(NSNotification *)aNotification
+- (void)setRepresentedMediaLibraryItems:(NSArray<VLCLibraryRepresentedItem *> *)representedMediaLibraryItems
 {
-    VLCPlayerController * const playerController = VLCMain.sharedInstance.playlistController.playerController;
-    VLCInputItem * const currentMediaItem = playerController.currentMedia;
-    [self setRepresentedInputItem:currentMediaItem];
-}
+    NSMutableArray<VLCInputItem *> * const inputItems = NSMutableArray.array;
+    for (VLCLibraryRepresentedItem * const representedItem in representedMediaLibraryItems) {
+        NSArray<VLCMediaLibraryMediaItem *> * const mediaItems = representedItem.item.mediaItems;
+        for (VLCMediaLibraryMediaItem * const mediaItem in mediaItems) {
+            [inputItems addObject:mediaItem.inputItem];
+        }
+    }
 
-- (void)setRepresentedInputItem:(VLCInputItem *)representedInputItem
-{
-    _representedInputItems = (representedInputItem == nil) ? @[] : @[representedInputItem];
-    [VLCLibraryImageCache thumbnailForInputItem:representedInputItem 
-                                 withCompletion:^(NSImage * const image) {
-        self->_artwork = image;
-    }];
-    [self updateRepresentation];
+    NSParameterAssert(inputItems.count > 0);
+    _representedInputItems = inputItems.copy;
+
+    NSMutableSet * const artworkMrlSet = NSMutableSet.set;
+
+    const dispatch_queue_t queue = dispatch_queue_create("vlc_infowindow_libraryitemimg_queue", 0);
+    dispatch_async(queue, ^{
+        NSMutableArray<NSImage *> * const artworkImages = NSMutableArray.array;
+        dispatch_group_t group = dispatch_group_create();
+
+        for (VLCLibraryRepresentedItem * const item in representedMediaLibraryItems) {
+            NSArray<VLCMediaLibraryMediaItem *> * const mediaItems = item.item.mediaItems;
+
+            for (VLCMediaLibraryMediaItem * const mediaItem in mediaItems) {
+                @synchronized (artworkMrlSet) {
+                    NSString * const itemArtworkMrl = mediaItem.smallArtworkMRL;
+                    if ([artworkMrlSet containsObject:itemArtworkMrl]) {
+                        continue;
+                    }
+                    [artworkMrlSet addObject:itemArtworkMrl];
+                }
+
+                @synchronized (artworkImages) {
+                    dispatch_group_enter(group);
+                    [VLCLibraryImageCache thumbnailForLibraryItem:mediaItem
+                                                   withCompletion:^(NSImage * const image) {
+                        if (image) {
+                            [artworkImages addObject:image];
+                        }
+                        dispatch_group_leave(group);
+                    }];
+                }
+            }
+        }
+
+        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
+
+        if (artworkImages.count == 0) {
+            _artwork = [NSImage imageNamed:@"noart.png"];
+            [self updateRepresentation];
+            return;
+        }
+
+        // Without an image set the button's size can be {{0, 0}, {0, 0}}
+        const CGFloat buttonHeight = self.artworkImageButton.frame.size.height;
+        const NSSize artworkSize =
+            buttonHeight == 0 ? NSMakeSize(256, 256) : NSMakeSize(buttonHeight, buttonHeight);
+        NSArray<NSValue *> * const frames =
+            [NSImage framesForCompositeImageSquareGridWithImages:artworkImages
+                                                            size:artworkSize
+                                                   gridItemCount:artworkImages.count];
+        _artwork = [NSImage compositeImageWithImages:artworkImages
+                                              frames:frames
+                                                size:artworkSize];
+
+        [self updateRepresentation];
+    });
 }
 
-- (void)setRepresentedMediaLibraryAudioGroup:(id<VLCMediaLibraryAudioGroupProtocol>)representedMediaLibraryAudioGroup
+- (void)setRepresentedInputItems:(NSArray<VLCInputItem *> *)representedInputItems
 {
-    NSMutableArray<VLCInputItem *> * const inputItems = NSMutableArray.array;
-    for (VLCMediaLibraryMediaItem * const mediaItem in representedMediaLibraryAudioGroup.mediaItems) {
-        [inputItems addObject:mediaItem.inputItem];
+    if (representedInputItems == _representedInputItems) {
+        return;
     }
 
-    _representedInputItems = [inputItems copy];
+    NSParameterAssert(representedInputItems.count > 0);
+    _representedInputItems = representedInputItems;
+
+    const dispatch_queue_t queue = dispatch_queue_create("vlc_infowindow_inputitemimg_queue", 0);
+    dispatch_async(queue, ^{
+        NSMutableArray<NSImage *> * const artworkImages = NSMutableArray.array;
+        dispatch_group_t group = dispatch_group_create();
+
+        for (VLCInputItem * const item in representedInputItems) {
+            @synchronized (artworkImages) {
+                dispatch_group_enter(group);
+                [VLCLibraryImageCache thumbnailForInputItem:item
+                                             withCompletion:^(NSImage * const image) {
+                    if (image) {
+                        [artworkImages addObject:image];
+                    }
+                    dispatch_group_leave(group);
+                }];
+            }
+        }
 
-    [VLCLibraryImageCache thumbnailForLibraryItem:representedMediaLibraryAudioGroup 
-                                   withCompletion:^(NSImage * const image) {
-        // HACK: Input items retrieved via an audio group do not acquire an artwork URL.
-        // To show something in the information window, set the small artwork from the audio group.
-        self->_artwork = image;
-    }];
+        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
 
-    [self updateRepresentation];
+        if (artworkImages.count == 0) {
+            _artwork = [NSImage imageNamed:@"noart.png"];
+            [self updateRepresentation];
+            return;
+        }
+
+        // Without an image set the button's size can be {{0, 0}, {0, 0}}
+        const CGFloat buttonHeight = self.artworkImageButton.frame.size.height;
+        const NSSize artworkSize =
+            buttonHeight == 0 ? NSMakeSize(256, 256) : NSMakeSize(buttonHeight, buttonHeight);
+        NSArray<NSValue *> * const frames =
+            [NSImage framesForCompositeImageSquareGridWithImages:artworkImages
+                                                            size:artworkSize
+                                                   gridItemCount:artworkImages.count];
+        _artwork = [NSImage compositeImageWithImages:artworkImages
+                                              frames:frames
+                                                size:artworkSize];
+
+        [self updateRepresentation];
+    });
 }
 
 - (void)mediaItemWasParsed:(NSNotification *)aNotification
@@ -305,17 +421,16 @@ _##field##TextField.delegate = self
 
 - (void)updateStatistics:(NSNotification *)aNotification
 {
-    if (!_statisticsEnabled)
-        return;
-
-    if (![self.window isVisible])
-        return;
-
-    VLCInputStats *inputStats = aNotification.userInfo[VLCPlayerInputStats];
-    if (!inputStats) {
-        [self initMediaPanelStats];
-        return;
-    }
+    NSAssert(self.representedInputItems.count == 1, @"Should not be updating stats for many items");
+    VLCPlayerController * const playerController =
+        VLCMain.sharedInstance.playlistController.playerController;
+    VLCInputItem * const currentPlayingItem = playerController.currentMedia;
+    VLCInputItem * const firstItem = self.representedInputItems.firstObject;
+    NSAssert([currentPlayingItem.MRL isEqualToString:firstItem.MRL],
+             @"Should not update statistics when items are different!");
+    NSAssert(_statisticsEnabled, @"Statistics should not be updated when they are disabled!");
+    VLCInputStats * const inputStats = aNotification.userInfo[VLCPlayerInputStats];
+    NSAssert(inputStats != nil, @"inputStats received for statistics update should not be nil!");
 
     /* input */
     [_inputReadBytesTextField setStringValue: [NSString stringWithFormat:
@@ -367,7 +482,9 @@ _##field##TextField.delegate = self
     _artworkImageButton.image = _artwork;
 
     if (!_mainMenuInstance) {
-        [self.window setTitle:inputItem.title];
+        dispatch_async(dispatch_get_main_queue(), ^{
+            self.window.title = inputItem.title;
+        });
     }
 }
 
@@ -375,17 +492,22 @@ _##field##TextField.delegate = self
 {
     NSParameterAssert(dict != nil);
 
-#define FILL_FIELD_FROM_DICT(field)                                         \
-{                                                                           \
-    NSString * const dictKey = [NSString stringWithUTF8String:#field];      \
-    NSString * const fieldValue = [dict objectForKey:dictKey];              \
-                                                                            \
-    if (fieldValue != nil) {                                                \
-        _##field##TextField.originalStateString = fieldValue;               \
-    } else {                                                                \
-        _##field##TextField.originalStateString = @"";                      \
-    }                                                                       \
-}                                                                           \
+#define FILL_FIELD_FROM_DICT(field)                                                 \
+{                                                                                   \
+    NSString * const dictKey = [NSString stringWithUTF8String:#field];              \
+    NSString * const fieldValue = [dict objectForKey:dictKey];                      \
+                                                                                    \
+    if ([fieldValue isEqualToString:VLCInputItemCommonDataDifferingFlagString]) {   \
+        _##field##TextField.placeholderString = _NS("(Multiple values)");           \
+        _##field##TextField.originalStateString = @"";                              \
+    } else if (fieldValue != nil) {                                                 \
+        _##field##TextField.placeholderString = @"";                                \
+        _##field##TextField.originalStateString = fieldValue;                       \
+    } else {                                                                        \
+        _##field##TextField.placeholderString = @"";                                \
+        _##field##TextField.originalStateString = @"";                              \
+    }                                                                               \
+}
 
     PERFORM_ACTION_ALL_TEXTFIELDS(FILL_FIELD_FROM_DICT);
 
@@ -416,7 +538,7 @@ _##field##TextField.originalStateString = @"";
         NSDictionary * const commonItemsData = commonInputItemData(_representedInputItems);
 
         if ([commonItemsData objectForKey:@"inputItem"]) {
-            [self setRepresentedInputItem:[commonItemsData objectForKey:@"inputItem"]];
+            self.representedInputItems = @[[commonItemsData objectForKey:@"inputItem"]];
         } else {
             [self fillWindowWithDictionaryData:commonItemsData];
         }
@@ -515,7 +637,9 @@ settingsChanged = settingsChanged || _##field##TextField.settingChanged;
 SET_INPUTITEM_PROP(field, field)                \
 
     for (VLCInputItem * const inputItem in inputItems) {
-        SET_INPUTITEM_PROP(title, name); // Input items do not have a title field
+        // We do not have a textfield for names; set the contents of the title field to the input
+        // item's name
+        SET_INPUTITEM_PROP(title, name);
         PERFORM_ACTION_READWRITE_TEXTFIELDS(SET_INPUTITEM_MATCHING_PROP);
 
         if (_newArtworkURL != nil) { // Artwork urls require their own handling


=====================================
modules/gui/macosx/playlist/VLCPlaylistMenuController.m
=====================================
@@ -152,17 +152,19 @@
         _informationWindowController = [[VLCInformationWindowController alloc] init];
     }
 
-    NSInteger selectedRow = self.playlistTableView.selectedRow;
-
-    if (selectedRow == -1)
-        return;
-
-    VLCPlaylistItem *playlistItem = [_playlistController.playlistModel playlistItemAtIndex:selectedRow];
-    if (playlistItem == nil)
-        return;
-
-    _informationWindowController.representedInputItem = playlistItem.inputItem;
+    NSMutableArray * const inputItems = NSMutableArray.array;
+    NSIndexSet * const selectedIndices = self.playlistTableView.selectedRowIndexes;
+
+    [selectedIndices enumerateIndexesUsingBlock:^(const NSUInteger idx, BOOL * const stop) {
+        VLCPlaylistItem * const item =
+            [self->_playlistController.playlistModel playlistItemAtIndex:idx];
+        if (item == nil) {
+            return;
+        }
+        [inputItems addObject:item.inputItem];
+    }];
 
+    _informationWindowController.representedInputItems = inputItems.copy;
     [_informationWindowController toggleWindow:sender];
 }
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/3df7b6e1187030591febd8e1bdd2712c0d6af132...438a5675baf76066b41b280e4e7397aa525289c2

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/3df7b6e1187030591febd8e1bdd2712c0d6af132...438a5675baf76066b41b280e4e7397aa525289c2
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