[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