瀏覽代碼

library: update the thumbnail to the last displayed frame when remember poisition is updated

(cherry picked from commit 3b460694d626eed130be1ce0560dcc57fc2c1dbd)
Felix Paul Kühne 10 年之前
父節點
當前提交
3fc601b416

+ 72 - 19
Sources/VLCPlaybackController.m

@@ -49,6 +49,7 @@
 
     BOOL _needsMetadataUpdate;
     BOOL _mediaWasJustStarted;
+    BOOL _recheckForExistingThumbnail;
 }
 
 @end
@@ -364,25 +365,76 @@
 
 - (void)_savePlaybackState
 {
-    if (self.fileFromMediaLibrary) {
-        @try {
-            MLFile *item = self.fileFromMediaLibrary;
-            item.lastPosition = @([_mediaPlayer position]);
-            item.lastAudioTrack = @(_mediaPlayer.currentAudioTrackIndex);
-            item.lastSubtitleTrack = @(_mediaPlayer.currentVideoSubTitleIndex);
-        }
-        @catch (NSException *exception) {
-            APLog(@"failed to save current media state - file removed?");
-        }
-    } else {
+    MLFile *fileItem = self.fileFromMediaLibrary;
+
+    if (!fileItem) {
         NSArray *files = [MLFile fileForURL:_mediaPlayer.media.url];
-        if (files.count > 0) {
-            MLFile *fileFromList = files.firstObject;
-            fileFromList.lastPosition = @([_mediaPlayer position]);
-            fileFromList.lastAudioTrack = @(_mediaPlayer.currentAudioTrackIndex);
-            fileFromList.lastSubtitleTrack = @(_mediaPlayer.currentVideoSubTitleIndex);
-        }
+        if (files.count > 0)
+            fileItem = files.firstObject;
+    }
+
+    if (!fileItem)
+        return;
+
+    @try {
+        float position = _mediaPlayer.position;
+        fileItem.lastPosition = @(position);
+        fileItem.lastAudioTrack = @(_mediaPlayer.currentAudioTrackIndex);
+        fileItem.lastSubtitleTrack = @(_mediaPlayer.currentVideoSubTitleIndex);
+
+        if (position > .95)
+            return;
+
+        NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
+        NSString* newThumbnailPath = [searchPaths[0] stringByAppendingPathComponent:@"VideoSnapshots"];
+        NSFileManager *fileManager = [NSFileManager defaultManager];
+
+        if (![fileManager fileExistsAtPath:newThumbnailPath])
+            [fileManager createDirectoryAtPath:newThumbnailPath withIntermediateDirectories:YES attributes:nil error:nil];
+
+        newThumbnailPath = [newThumbnailPath stringByAppendingPathComponent:fileItem.objectID.URIRepresentation.lastPathComponent];
+        [_mediaPlayer saveVideoSnapshotAt:newThumbnailPath withWidth:0 andHeight:0];
+
+        _recheckForExistingThumbnail = YES;
+        [self performSelector:@selector(_updateStoredThumbnailForFile:) withObject:fileItem afterDelay:.25];
     }
+    @catch (NSException *exception) {
+        APLog(@"failed to save current media state - file removed?");
+    }
+}
+
+- (void)_updateStoredThumbnailForFile:(MLFile *)fileItem
+{
+    NSFileManager *fileManager = [NSFileManager defaultManager];
+    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
+    NSString* newThumbnailPath = [searchPaths[0] stringByAppendingPathComponent:@"VideoSnapshots"];
+    newThumbnailPath = [newThumbnailPath stringByAppendingPathComponent:fileItem.objectID.URIRepresentation.lastPathComponent];
+
+    if (![fileManager fileExistsAtPath:newThumbnailPath]) {
+        if (_recheckForExistingThumbnail) {
+            [self performSelector:@selector(_updateStoredThumbnailForFile:) withObject:fileItem afterDelay:1.];
+            _recheckForExistingThumbnail = NO;
+        } else
+            return;
+    }
+
+    UIImage *newThumbnail = [UIImage imageWithContentsOfFile:newThumbnailPath];
+    if (!newThumbnail) {
+        if (_recheckForExistingThumbnail) {
+            [self performSelector:@selector(_updateStoredThumbnailForFile:) withObject:fileItem afterDelay:1.];
+            _recheckForExistingThumbnail = NO;
+        } else
+            return;
+    }
+
+    @try {
+        [fileItem setComputedThumbnailScaledForDevice:newThumbnail];
+    }
+    @catch (NSException *exception) {
+        APLog(@"updating thumbnail failed");
+    }
+
+    [fileManager removeItemAtPath:newThumbnailPath error:nil];
 }
 
 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
@@ -505,9 +557,10 @@
 #pragma mark - playback controls
 - (void)playPause
 {
-    if ([_mediaPlayer isPlaying])
+    if ([_mediaPlayer isPlaying]) {
         [_listPlayer pause];
-    else
+        [self _savePlaybackState];
+    } else
         [_listPlayer play];
 }
 

+ 11 - 0
Sources/VLCPlaylistCollectionViewCell.m

@@ -128,6 +128,7 @@
         [_mediaObject removeObserver:self forKeyPath:@"album"];
         [_mediaObject removeObserver:self forKeyPath:@"artist"];
         [_mediaObject removeObserver:self forKeyPath:@"genre"];
+        [[NSNotificationCenter defaultCenter] removeObserver:self];
         [(MLFile*)_mediaObject didHide];
     }
 }
@@ -166,6 +167,10 @@
         [_mediaObject addObserver:self forKeyPath:@"album" options:0 context:nil];
         [_mediaObject addObserver:self forKeyPath:@"artist" options:0 context:nil];
         [_mediaObject addObserver:self forKeyPath:@"genre" options:0 context:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(thumbnailWasUpdated:)
+                                                     name:MLFileThumbnailWasUpdated
+                                                   object:nil];
         [(MLFile*)_mediaObject willDisplay];
     }
 }
@@ -510,4 +515,10 @@
     return !self.metaDataLabel.hidden;
 }
 
+- (void)thumbnailWasUpdated:(NSNotification *)aNotification
+{
+    self.thumbnailView.contentMode = UIViewContentModeScaleAspectFill;
+    self.thumbnailView.image = [VLCThumbnailsCache thumbnailForManagedObject:self.mediaObject refreshCache:YES];
+}
+
 @end

+ 11 - 0
Sources/VLCPlaylistTableViewCell.m

@@ -93,6 +93,7 @@
         [_mediaObject removeObserver:self forKeyPath:@"album"];
         [_mediaObject removeObserver:self forKeyPath:@"artist"];
         [_mediaObject removeObserver:self forKeyPath:@"genre"];
+        [[NSNotificationCenter defaultCenter] removeObserver:self];
         [(MLFile*)_mediaObject didHide];
     }
 }
@@ -131,6 +132,10 @@
         [_mediaObject addObserver:self forKeyPath:@"album" options:0 context:nil];
         [_mediaObject addObserver:self forKeyPath:@"artist" options:0 context:nil];
         [_mediaObject addObserver:self forKeyPath:@"genre" options:0 context:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(thumbnailWasUpdated:)
+                                                     name:MLFileThumbnailWasUpdated
+                                                   object:nil];
         [(MLFile*)_mediaObject willDisplay];
     }
 }
@@ -525,4 +530,10 @@
     [UIView animateWithDuration:animationDuration animations:animationBlock completion:completionBlock];
 }
 
+- (void)thumbnailWasUpdated:(NSNotification *)aNotification
+{
+    self.thumbnailView.contentMode = UIViewContentModeScaleAspectFill;
+    self.thumbnailView.image = [VLCThumbnailsCache thumbnailForManagedObject:self.mediaObject refreshCache:YES];
+}
+
 @end

+ 2 - 0
Sources/VLCThumbnailsCache.h

@@ -16,6 +16,8 @@
 
 + (UIImage *)thumbnailForManagedObject:(NSManagedObject *)object;
 
++ (UIImage *)thumbnailForManagedObject:(NSManagedObject *)object refreshCache:(BOOL)refreshCache;
+
 + (UIImage *)thumbnailForManagedObject:(NSManagedObject *)object toFitRect:(CGRect)rect shouldReplaceCache:(BOOL)replaceCache;
 
 @end

+ 32 - 17
Sources/VLCThumbnailsCache.m

@@ -75,21 +75,27 @@
 
 + (UIImage *)thumbnailForManagedObject:(NSManagedObject *)object
 {
+    return [self thumbnailForManagedObject:object refreshCache:NO];
+}
+
++ (UIImage *)thumbnailForManagedObject:(NSManagedObject *)object
+                          refreshCache:(BOOL)refreshCache
+{
     UIImage *thumbnail;
     VLCThumbnailsCache *cache = [VLCThumbnailsCache sharedThumbnailCache];
     if ([object isKindOfClass:[MLShow class]]) {
-        thumbnail = [cache thumbnailForShow:(MLShow *)object];
+        thumbnail = [cache thumbnailForShow:(MLShow *)object refreshCache:refreshCache];
     } else if ([object isKindOfClass:[MLShowEpisode class]]) {
         MLFile *anyFileFromEpisode = [(MLShowEpisode *)object files].anyObject;
-        thumbnail = [cache thumbnailForMediaFile:anyFileFromEpisode];
+        thumbnail = [cache thumbnailForMediaFile:anyFileFromEpisode refreshCache:refreshCache];
     } else if ([object isKindOfClass:[MLLabel class]]) {
-        thumbnail = [cache thumbnailForLabel:(MLLabel *)object];
+        thumbnail = [cache thumbnailForLabel:(MLLabel *)object refreshCache:refreshCache];
     } else if ([object isKindOfClass:[MLAlbum class]]) {
-        thumbnail = [cache thumbnailForAlbum:(MLAlbum *)object];
+        thumbnail = [cache thumbnailForAlbum:(MLAlbum *)object refreshCache:refreshCache];
     } else if ([object isKindOfClass:[MLAlbumTrack class]]) {
-        thumbnail = [cache thumbnailForAlbumTrack:(MLAlbumTrack *)object];
+        thumbnail = [cache thumbnailForAlbumTrack:(MLAlbumTrack *)object refreshCache:refreshCache];
     } else {
-        thumbnail = [cache thumbnailForMediaFile:(MLFile *)object];
+        thumbnail = [cache thumbnailForMediaFile:(MLFile *)object refreshCache:refreshCache];
     }
     return thumbnail;
 }
@@ -117,16 +123,19 @@
         [_thumbnailCache setObject:image forKey:objID];
 }
 
-- (UIImage *)thumbnailForMediaFile:(MLFile *)mediaFile
+- (UIImage *)thumbnailForMediaFile:(MLFile *)mediaFile refreshCache:(BOOL)refreshCache
 {
     if (mediaFile == nil || mediaFile.objectID == nil)
         return nil;
 
     NSManagedObjectID *objID = mediaFile.objectID;
-    UIImage *displayedImage = [_thumbnailCache objectForKey:objID];
+    UIImage *displayedImage;
 
-    if (displayedImage)
-        return displayedImage;
+    if (!refreshCache) {
+        displayedImage = [_thumbnailCache objectForKey:objID];
+        if (displayedImage)
+            return displayedImage;
+    }
 
     if (!displayedImage) {
         __block UIImage *computedImage = nil;
@@ -146,7 +155,7 @@
     return displayedImage;
 }
 
-- (UIImage *)thumbnailForShow:(MLShow *)mediaShow
+- (UIImage *)thumbnailForShow:(MLShow *)mediaShow refreshCache:(BOOL)refreshCache
 {
     NSManagedObjectID *objID = mediaShow.objectID;
     UIImage *displayedImage;
@@ -158,6 +167,9 @@
     if (previousCount.unsignedIntegerValue != count)
         forceRefresh = YES;
 
+    if (refreshCache)
+        forceRefresh = YES;
+
     if (!forceRefresh) {
         displayedImage = [_thumbnailCache objectForKey:objID];
         if (displayedImage)
@@ -183,7 +195,7 @@
     return displayedImage;
 }
 
-- (UIImage *)thumbnailForLabel:(MLLabel *)mediaLabel
+- (UIImage *)thumbnailForLabel:(MLLabel *)mediaLabel refreshCache:(BOOL)refreshCache
 {
     NSManagedObjectID *objID = mediaLabel.objectID;
     UIImage *displayedImage;
@@ -195,6 +207,9 @@
     if (previousCount.unsignedIntegerValue != count)
         forceRefresh = YES;
 
+    if (refreshCache)
+        forceRefresh = YES;
+
     if (!forceRefresh) {
         displayedImage = [_thumbnailCache objectForKey:objID];
         if (displayedImage)
@@ -215,7 +230,7 @@
     return displayedImage;
 }
 
-- (UIImage *)thumbnailForAlbum:(MLAlbum *)album
+- (UIImage *)thumbnailForAlbum:(MLAlbum *)album refreshCache:(BOOL)refreshCache
 {
     __block MLAlbumTrack *track = nil;
     void (^getFileBlock)(void) = ^(){
@@ -226,10 +241,10 @@
     else
         dispatch_sync(dispatch_get_main_queue(), getFileBlock);
 
-    return [self thumbnailForAlbumTrack:track];
+    return [self thumbnailForAlbumTrack:track refreshCache:refreshCache];
 }
 
-- (UIImage *)thumbnailForAlbumTrack:(MLAlbumTrack *)albumTrack
+- (UIImage *)thumbnailForAlbumTrack:(MLAlbumTrack *)albumTrack refreshCache:(BOOL)refreshCache
 {
     __block MLFile *anyFileFromAnyTrack = nil;
     void (^getFileBlock)(void) = ^(){
@@ -239,7 +254,7 @@
         getFileBlock();
     else
         dispatch_sync(dispatch_get_main_queue(), getFileBlock);
-    return [self thumbnailForMediaFile:anyFileFromAnyTrack];
+    return [self thumbnailForMediaFile:anyFileFromAnyTrack refreshCache:refreshCache];
 }
 
 - (UIImage *)clusterThumbFromFiles:(NSArray *)files andNumber:(NSUInteger)fileNumber blur:(BOOL)blurImage
@@ -276,7 +291,7 @@
     NSUInteger iter = files.count < fileNumber ? files.count : fileNumber;
     for (NSUInteger i = 0; i < iter; i++) {
         MLFile *file =  [files objectAtIndex:i];
-        clusterThumb = [self thumbnailForMediaFile:file];
+        clusterThumb = [self thumbnailForMediaFile:file refreshCache:NO];
         CGContextRef context = UIGraphicsGetCurrentContext();
         CGFloat imagePartWidth = (imageSize.width / iter);
         //the rect in which the image should be drawn