macosx/library: add an image cache to improve responsiveness

This commit is contained in:
Felix Paul Kühne 2020-01-26 14:58:24 +01:00
parent 2601a1725d
commit bd91af604b
13 changed files with 180 additions and 41 deletions

View File

@ -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 */,

View File

@ -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 \

View File

@ -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"];
}

View File

@ -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"];
}

View File

@ -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"];
}

View File

@ -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;

View File

@ -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

View File

@ -175,6 +175,7 @@ extern const long long int VLCMediaLibraryMediaItemDurationDenominator;
@property (readonly) NSString *title;
@property (readonly, nullable) NSString *smallArtworkMRL;
@property (readonly, nullable) NSImage *smallArtworkImage;
@property (readonly) BOOL smallArtworkGenerated;
@property (readonly) BOOL favorited;

View File

@ -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);

View File

@ -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
@class VLCMediaLibraryMediaItem;
@interface VLCLibraryImageCache : NSObject
+ (NSImage *)thumbnailForMediaItemWithID:(int64_t)libraryID;
+ (NSImage *)thumbnailForMediaItem:(VLCMediaLibraryMediaItem *)mediaItem;
@end
NS_ASSUME_NONNULL_END

View File

@ -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;
@interface VLCLibraryImageCache()
{
NSCache *_imageCache;
vlc_medialibrary_t *_p_libraryInstance;
}
@end
@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);
}
@end

View File

@ -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

View File

@ -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