[vlc-commits] macosx/library: add an image cache to improve responsiveness

Felix Paul Kühne git at videolan.org
Sun Jan 26 15:00:03 CET 2020


vlc | branch: master | Felix Paul Kühne <felix at feepk.net> | Sun Jan 26 14:58:24 2020 +0100| [bd91af604b4bf24075e1d5f868a5ebf3d209eeb4] | committer: Felix Paul Kühne

macosx/library: add an image cache to improve responsiveness

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=bd91af604b4bf24075e1d5f868a5ebf3d209eeb4
---

 .../package/macosx/VLC.xcodeproj/project.pbxproj   |   6 +
 modules/gui/macosx/Makefile.am                     |   2 +
 .../macosx/library/VLCLibraryAlbumTableCellView.m  |   7 +-
 .../gui/macosx/library/VLCLibraryAudioDataSource.m |   7 +-
 .../macosx/library/VLCLibraryCollectionViewItem.m  |   9 +-
 modules/gui/macosx/library/VLCLibraryController.h  |   1 -
 modules/gui/macosx/library/VLCLibraryController.m  |  17 ---
 modules/gui/macosx/library/VLCLibraryDataTypes.h   |   1 +
 modules/gui/macosx/library/VLCLibraryDataTypes.m   |   6 +
 modules/gui/macosx/library/VLCLibraryImageCache.h  |  36 ++++++
 modules/gui/macosx/library/VLCLibraryImageCache.m  | 123 +++++++++++++++++++++
 .../macosx/library/VLCLibraryInformationPanel.m    |   4 +-
 po/POTFILES.in                                     |   2 +
 13 files changed, 180 insertions(+), 41 deletions(-)

diff --git a/extras/package/macosx/VLC.xcodeproj/project.pbxproj b/extras/package/macosx/VLC.xcodeproj/project.pbxproj
index 4534baf5cc..38aa696d99 100644
--- a/extras/package/macosx/VLC.xcodeproj/project.pbxproj
+++ b/extras/package/macosx/VLC.xcodeproj/project.pbxproj
@@ -139,6 +139,7 @@
 		7D903EAF224392B400917358 /* timespec_get.c in Sources */ = {isa = PBXBuildFile; fileRef = 7D903EAE224392B400917358 /* timespec_get.c */; };
 		7D903EB6224394BE00917358 /* specific.c in Sources */ = {isa = PBXBuildFile; fileRef = 7D903EB5224394BE00917358 /* specific.c */; };
 		7D903EB92243952100917358 /* threads.c in Sources */ = {isa = PBXBuildFile; fileRef = 7D903EB82243952100917358 /* threads.c */; };
+		7D92AF2123DDCA8D00D81EA3 /* VLCLibraryImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D92AF2023DDCA8D00D81EA3 /* VLCLibraryImageCache.m */; };
 		7D93D8FC2316C2DC001C0063 /* VLCCustomCropArWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D93D8FB2316C2DC001C0063 /* VLCCustomCropArWindowController.m */; };
 		7DB40D2A20CBCEB500F63173 /* VLCMainMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB40D2920CBCEB500F63173 /* VLCMainMenu.m */; };
 		7DB40D2D20CBCEC200F63173 /* VLCStatusBarIcon.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB40D2B20CBCEC200F63173 /* VLCStatusBarIcon.m */; };
@@ -540,6 +541,8 @@
 		7D903EAE224392B400917358 /* timespec_get.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = timespec_get.c; path = ../../../../compat/timespec_get.c; sourceTree = "<group>"; };
 		7D903EB5224394BE00917358 /* specific.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = specific.c; path = ../../../src/darwin/specific.c; sourceTree = "<group>"; };
 		7D903EB82243952100917358 /* threads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = threads.c; path = ../../../../src/misc/threads.c; sourceTree = "<group>"; };
+		7D92AF1F23DDCA8D00D81EA3 /* VLCLibraryImageCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCLibraryImageCache.h; sourceTree = "<group>"; };
+		7D92AF2023DDCA8D00D81EA3 /* VLCLibraryImageCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryImageCache.m; sourceTree = "<group>"; };
 		7D93D8F92316C142001C0063 /* VLCCustomCropARPanel.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = VLCCustomCropARPanel.xib; sourceTree = "<group>"; };
 		7D93D8FA2316C2DC001C0063 /* VLCCustomCropArWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCCustomCropArWindowController.h; sourceTree = "<group>"; };
 		7D93D8FB2316C2DC001C0063 /* VLCCustomCropArWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCCustomCropArWindowController.m; sourceTree = "<group>"; };
@@ -1052,6 +1055,8 @@
 				7DFBDCAA2269E77F00B700A5 /* VLCLibraryModel.m */,
 				7DFBDCB2226CD00900B700A5 /* VLCLibraryDataTypes.h */,
 				7DFBDCB3226CD00900B700A5 /* VLCLibraryDataTypes.m */,
+				7D92AF1F23DDCA8D00D81EA3 /* VLCLibraryImageCache.h */,
+				7D92AF2023DDCA8D00D81EA3 /* VLCLibraryImageCache.m */,
 				7DFBDCAC2269ED0C00B700A5 /* VLCLibraryVideoDataSource.h */,
 				7DFBDCAD2269ED0C00B700A5 /* VLCLibraryVideoDataSource.m */,
 				7DE2F0422282C84A0040DD0A /* VLCLibraryAudioDataSource.h */,
@@ -1754,6 +1759,7 @@
 				7DE9C7DD220728420089108F /* VLCPlayerController.m in Sources */,
 				7D93D8FC2316C2DC001C0063 /* VLCCustomCropArWindowController.m in Sources */,
 				1C3113941E508C6900D4DD76 /* VLCAddonsWindowController.m in Sources */,
+				7D92AF2123DDCA8D00D81EA3 /* VLCLibraryImageCache.m in Sources */,
 				7D2E0EDE20CD206F0033A221 /* VLCVideoWindowCommon.m in Sources */,
 				1C3113961E508C6900D4DD76 /* applescript.m in Sources */,
 				1C3113981E508C6900D4DD76 /* VLCAudioEffectsWindowController.m in Sources */,
diff --git a/modules/gui/macosx/Makefile.am b/modules/gui/macosx/Makefile.am
index 53d36083f9..f273ccb7cf 100644
--- a/modules/gui/macosx/Makefile.am
+++ b/modules/gui/macosx/Makefile.am
@@ -64,6 +64,8 @@ libmacosx_plugin_la_SOURCES = \
 	gui/macosx/library/VLCLibraryController.m \
 	gui/macosx/library/VLCLibraryDataTypes.h \
 	gui/macosx/library/VLCLibraryDataTypes.m \
+	gui/macosx/library/VLCLibraryImageCache.h \
+	gui/macosx/library/VLCLibraryImageCache.m \
 	gui/macosx/library/VLCLibraryInformationPanel.h \
 	gui/macosx/library/VLCLibraryInformationPanel.m \
 	gui/macosx/library/VLCLibraryMenuController.h \
diff --git a/modules/gui/macosx/library/VLCLibraryAlbumTableCellView.m b/modules/gui/macosx/library/VLCLibraryAlbumTableCellView.m
index 4fc79b3ae8..c02442c776 100644
--- a/modules/gui/macosx/library/VLCLibraryAlbumTableCellView.m
+++ b/modules/gui/macosx/library/VLCLibraryAlbumTableCellView.m
@@ -213,12 +213,7 @@ const CGFloat LayoutSpacer;
 
     VLCMediaLibraryMediaItem *mediaItem = _tracks[row];
 
-    NSImage *image;
-    if (mediaItem.smallArtworkGenerated) {
-        if (mediaItem.smallArtworkMRL.length > 0) {
-            image = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:mediaItem.smallArtworkMRL]];
-        }
-    }
+    NSImage *image = mediaItem.smallArtworkImage;
     if (!image) {
         image = [NSImage imageNamed: @"noart.png"];
     }
diff --git a/modules/gui/macosx/library/VLCLibraryAudioDataSource.m b/modules/gui/macosx/library/VLCLibraryAudioDataSource.m
index 6512f27685..d711d96d52 100644
--- a/modules/gui/macosx/library/VLCLibraryAudioDataSource.m
+++ b/modules/gui/macosx/library/VLCLibraryAudioDataSource.m
@@ -189,12 +189,7 @@ static NSString *VLCAudioLibraryCellIdentifier = @"VLCAudioLibraryCellIdentifier
         {
             VLCMediaLibraryMediaItem *mediaItem = _displayedCollection[row];
 
-            NSImage *image;
-            if (mediaItem.smallArtworkGenerated) {
-                if (mediaItem.smallArtworkMRL.length > 0) {
-                    image = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:mediaItem.smallArtworkMRL]];
-                }
-            }
+            NSImage *image = mediaItem.smallArtworkImage;
             if (!image) {
                 image = [NSImage imageNamed: @"noart.png"];
             }
diff --git a/modules/gui/macosx/library/VLCLibraryCollectionViewItem.m b/modules/gui/macosx/library/VLCLibraryCollectionViewItem.m
index ac97cfe211..f6487a17d9 100644
--- a/modules/gui/macosx/library/VLCLibraryCollectionViewItem.m
+++ b/modules/gui/macosx/library/VLCLibraryCollectionViewItem.m
@@ -185,14 +185,7 @@ const CGFloat VLCLibraryCollectionViewItemMaximumDisplayedProgress = 0.95;
 
 - (NSImage *)imageForMedia
 {
-    NSImage *image;
-    if (_representedMediaItem.smallArtworkGenerated) {
-        image = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:_representedMediaItem.smallArtworkMRL]];
-    } else {
-        if (_representedMediaItem.mediaType != VLC_ML_MEDIA_TYPE_AUDIO) {
-            [_libraryController attemptToGenerateThumbnailForMediaItem:_representedMediaItem];
-        }
-    }
+    NSImage *image = _representedMediaItem.smallArtworkImage;
     if (!image) {
         image = [NSImage imageNamed: @"noart.png"];
     }
diff --git a/modules/gui/macosx/library/VLCLibraryController.h b/modules/gui/macosx/library/VLCLibraryController.h
index 95a19981f1..cb18fe436f 100644
--- a/modules/gui/macosx/library/VLCLibraryController.h
+++ b/modules/gui/macosx/library/VLCLibraryController.h
@@ -36,7 +36,6 @@ NS_ASSUME_NONNULL_BEGIN
 - (int)appendItemToPlaylist:(VLCMediaLibraryMediaItem *)mediaItem playImmediately:(BOOL)playImmediately;
 - (int)appendItemsToPlaylist:(NSArray <VLCMediaLibraryMediaItem *> *)mediaItemArray playFirstItemImmediately:(BOOL)playFirstItemImmediately;
 - (void)showItemInFinder:(VLCMediaLibraryMediaItem *)mediaItem;
-- (int)attemptToGenerateThumbnailForMediaItem:(VLCMediaLibraryMediaItem *)mediaItem;
 
 - (int)addFolderWithFileURL:(NSURL *)fileURL;
 - (int)banFolderWithFileURL:(NSURL *)fileURL;
diff --git a/modules/gui/macosx/library/VLCLibraryController.m b/modules/gui/macosx/library/VLCLibraryController.m
index a0e955019b..b20b48ade8 100644
--- a/modules/gui/macosx/library/VLCLibraryController.m
+++ b/modules/gui/macosx/library/VLCLibraryController.m
@@ -30,10 +30,6 @@
 
 #import <vlc_media_library.h>
 
-uint32_t kVLCDesiredThumbnailWidth = 512;
-uint32_t kVLCDesiredThumbnailHeight = 320;
-float kVLCDefaultThumbnailPosition = .15;
-
 @interface VLCLibraryController()
 {
     vlc_medialibrary_t *_p_libraryInstance;
@@ -140,19 +136,6 @@ float kVLCDefaultThumbnailPosition = .15;
     }
 }
 
-- (int)attemptToGenerateThumbnailForMediaItem:(VLCMediaLibraryMediaItem *)mediaItem
-{
-    if (!_p_libraryInstance) {
-        return VLC_ENOOBJ;
-    }
-    return vlc_ml_media_generate_thumbnail(_p_libraryInstance,
-                                           mediaItem.libraryID,
-                                           VLC_ML_THUMBNAIL_SMALL,
-                                           kVLCDesiredThumbnailWidth,
-                                           kVLCDesiredThumbnailHeight,
-                                           kVLCDefaultThumbnailPosition);
-}
-
 #pragma mark - folder management
 
 - (int)addFolderWithFileURL:(NSURL *)fileURL
diff --git a/modules/gui/macosx/library/VLCLibraryDataTypes.h b/modules/gui/macosx/library/VLCLibraryDataTypes.h
index 01f67a81c1..bada8467f8 100644
--- a/modules/gui/macosx/library/VLCLibraryDataTypes.h
+++ b/modules/gui/macosx/library/VLCLibraryDataTypes.h
@@ -175,6 +175,7 @@ extern const long long int VLCMediaLibraryMediaItemDurationDenominator;
 @property (readonly) NSString *title;
 
 @property (readonly, nullable) NSString *smallArtworkMRL;
+ at property (readonly, nullable) NSImage *smallArtworkImage;
 
 @property (readonly) BOOL smallArtworkGenerated;
 @property (readonly) BOOL favorited;
diff --git a/modules/gui/macosx/library/VLCLibraryDataTypes.m b/modules/gui/macosx/library/VLCLibraryDataTypes.m
index d29094da13..57555e0879 100644
--- a/modules/gui/macosx/library/VLCLibraryDataTypes.m
+++ b/modules/gui/macosx/library/VLCLibraryDataTypes.m
@@ -25,6 +25,7 @@
 #import "main/VLCMain.h"
 #import "extensions/NSString+Helpers.h"
 #import "library/VLCInputItem.h"
+#import "library/VLCLibraryImageCache.h"
 
 #import <vlc_url.h>
 
@@ -461,6 +462,11 @@ NSString *VLCMediaLibraryMediaItemLibraryID = @"VLCMediaLibraryMediaItemLibraryI
     }
 }
 
+- (NSImage *)smallArtworkImage
+{
+    return [VLCLibraryImageCache thumbnailForMediaItem:self];
+}
+
 - (VLCInputItem *)inputItem
 {
     input_item_t *p_inputItem = vlc_ml_get_input_item(_p_mediaLibrary, _libraryID);
diff --git a/modules/gui/macosx/library/VLCLibraryImageCache.h b/modules/gui/macosx/library/VLCLibraryImageCache.h
new file mode 100644
index 0000000000..18e6cef04d
--- /dev/null
+++ b/modules/gui/macosx/library/VLCLibraryImageCache.h
@@ -0,0 +1,36 @@
+/*****************************************************************************
+* VLCLibraryImageCache.h: MacOS X interface module
+*****************************************************************************
+* Copyright (C) 2020 VLC authors and VideoLAN
+*
+* Authors: Felix Paul Kühne <fkuehne # videolan -dot- org>
+*
+* 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 <Cocoa/Cocoa.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+ at class VLCMediaLibraryMediaItem;
+
+ at interface VLCLibraryImageCache : NSObject
+
++ (NSImage *)thumbnailForMediaItemWithID:(int64_t)libraryID;
++ (NSImage *)thumbnailForMediaItem:(VLCMediaLibraryMediaItem *)mediaItem;
+
+ at end
+
+NS_ASSUME_NONNULL_END
diff --git a/modules/gui/macosx/library/VLCLibraryImageCache.m b/modules/gui/macosx/library/VLCLibraryImageCache.m
new file mode 100644
index 0000000000..29255f2873
--- /dev/null
+++ b/modules/gui/macosx/library/VLCLibraryImageCache.m
@@ -0,0 +1,123 @@
+/*****************************************************************************
+* VLCLibraryImageCache.m: MacOS X interface module
+*****************************************************************************
+* Copyright (C) 2020 VLC authors and VideoLAN
+*
+* Authors: Felix Paul Kühne <fkuehne # videolan -dot- org>
+*
+* 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 "VLCLibraryImageCache.h"
+#import "library/VLCLibraryDataTypes.h"
+#import "main/VLCMain.h"
+
+NSUInteger kVLCMaximumImageCacheSize = 50;
+uint32_t kVLCDesiredThumbnailWidth = 512;
+uint32_t kVLCDesiredThumbnailHeight = 320;
+float kVLCDefaultThumbnailPosition = .15;
+
+
+ at interface VLCLibraryImageCache()
+{
+    NSCache *_imageCache;
+    vlc_medialibrary_t *_p_libraryInstance;
+}
+
+ at end
+
+ at implementation VLCLibraryImageCache
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        _imageCache = [[NSCache alloc] init];
+        _imageCache.countLimit = kVLCMaximumImageCacheSize;
+    }
+    return self;
+}
+
++ (instancetype)sharedImageCache
+{
+    static dispatch_once_t onceToken;
+    static VLCLibraryImageCache *sharedImageCache;
+    dispatch_once(&onceToken, ^{
+        sharedImageCache = [[VLCLibraryImageCache alloc] init];
+    });
+    return sharedImageCache;
+}
+
++ (NSImage *)thumbnailForMediaItemWithID:(int64_t)libraryID
+{
+    return [[VLCLibraryImageCache sharedImageCache] imageForMediaItemWithID:libraryID];
+}
+
++ (NSImage *)thumbnailForMediaItem:(VLCMediaLibraryMediaItem *)mediaItem
+{
+    return [[VLCLibraryImageCache sharedImageCache] imageForMediaItem:mediaItem];
+}
+
+- (NSImage *)imageForMediaItem:(VLCMediaLibraryMediaItem *)mediaItem
+{
+    NSImage *cachedImage = [_imageCache objectForKey:@(mediaItem.libraryID)];
+    if (cachedImage) {
+        return cachedImage;
+    }
+    return [self smallThumbnailForMediaItem:mediaItem];
+}
+
+- (NSImage *)imageForMediaItemWithID:(int64_t)libraryID
+{
+    NSNumber *libraryIDnumber = @(libraryID);
+    NSImage *cachedImage = [_imageCache objectForKey:libraryIDnumber];
+    if (cachedImage) {
+        return cachedImage;
+    }
+    VLCMediaLibraryMediaItem *mediaItem = [VLCMediaLibraryMediaItem mediaItemForLibraryID:libraryID];
+    return [self smallThumbnailForMediaItem:mediaItem];
+}
+
+- (NSImage *)smallThumbnailForMediaItem:(VLCMediaLibraryMediaItem *)mediaItem
+{
+    NSImage *image;
+    if (mediaItem.smallArtworkGenerated) {
+        image = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:mediaItem.smallArtworkMRL]];
+    } else {
+        if (mediaItem.mediaType != VLC_ML_MEDIA_TYPE_AUDIO) {
+            [self generateThumbnailForMediaItem:mediaItem.libraryID];
+        }
+    }
+    if (image) {
+        [_imageCache setObject:image forKey:@(mediaItem.libraryID)];
+    }
+    return image;
+}
+
+- (void)generateThumbnailForMediaItem:(int64_t)mediaID
+{
+    if (!_p_libraryInstance) {
+        _p_libraryInstance = vlc_ml_instance_get(getIntf());
+    }
+    vlc_ml_media_generate_thumbnail(_p_libraryInstance,
+                                    mediaID,
+                                    VLC_ML_THUMBNAIL_SMALL,
+                                    kVLCDesiredThumbnailWidth,
+                                    kVLCDesiredThumbnailHeight,
+                                    kVLCDefaultThumbnailPosition);
+}
+
+ at end
diff --git a/modules/gui/macosx/library/VLCLibraryInformationPanel.m b/modules/gui/macosx/library/VLCLibraryInformationPanel.m
index 793105f6d3..54b0e0a3e6 100644
--- a/modules/gui/macosx/library/VLCLibraryInformationPanel.m
+++ b/modules/gui/macosx/library/VLCLibraryInformationPanel.m
@@ -92,9 +92,7 @@
 
     self.multiLineTextLabel.stringValue = textContent;
     self.window.title = _representedMediaItem.title;
-    if (_representedMediaItem.smallArtworkMRL) {
-        self.imageView.image = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:_representedMediaItem.smallArtworkMRL]];
-    }
+    self.imageView.image = _representedMediaItem.smallArtworkImage;
 }
 
 @end
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2ca218a621..21287b2f21 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -471,6 +471,8 @@ modules/gui/macosx/library/VLCLibraryController.h
 modules/gui/macosx/library/VLCLibraryController.m
 modules/gui/macosx/library/VLCLibraryDataTypes.h
 modules/gui/macosx/library/VLCLibraryDataTypes.m
+modules/gui/macosx/library/VLCLibraryImageCache.h
+modules/gui/macosx/library/VLCLibraryImageCache.m
 modules/gui/macosx/library/VLCLibraryInformationPanel.h
 modules/gui/macosx/library/VLCLibraryInformationPanel.m
 modules/gui/macosx/library/VLCLibraryMenuController.h



More information about the vlc-commits mailing list