Browse Source

ATV playback: show artist imagery based on MetaDataFetcherKit when playing audio-only content

Felix Paul Kühne 9 years ago
parent
commit
68846b268e
3 changed files with 182 additions and 6 deletions
  1. 3 2
      Podfile
  2. 19 3
      Podfile.lock
  3. 160 1
      VLC for Apple TV/Playback/VLCFullscreenMovieTVViewController.m

+ 3 - 2
Podfile

@@ -30,6 +30,7 @@ pod 'SSKeychain', :git => 'git://github.com/fkuehne/sskeychain.git' #iCloud Keyc
 pod 'box-ios-sdk-v2', :git => 'git://github.com/fkuehne/box-ios-sdk-v2.git' #has tvOS support added
 pod 'upnpx', '~>1.3.6'
 pod 'CocoaHTTPServer', :git => 'git://github.com/fkuehne/CocoaHTTPServer.git' # has our fixes
-pod 'MetaDataFetcherKit', '~>0.1.2'
-
+pod 'MetaDataFetcherKit', '~>0.1.5'
+pod 'MSWeakTimer', :git => 'git://github.com/fkuehne/MSWeakTimer.git' #has tvOS support added
+pod 'JSAnimatedImagesView', :git => 'git://github.com/fkuehne/JSAnimatedImagesView.git' #has tvOS support added
 end

+ 19 - 3
Podfile.lock

@@ -20,8 +20,10 @@ PODS:
   - CocoaHTTPServer (2.3)
   - HockeySDK (3.6.4)
   - InAppSettingsKit (2.2.2)
-  - MetaDataFetcherKit (0.1.3):
+  - JSAnimatedImagesView (1.0.1)
+  - MetaDataFetcherKit (0.1.5):
     - AFNetworking (= 3.0.0-beta.1)
+  - MSWeakTimer (1.1.1)
   - OBSlider (1.1.0)
   - RESideMenu (4.0.7)
   - SSKeychain (1.2.3)
@@ -33,7 +35,9 @@ DEPENDENCIES:
   - HockeySDK (~> 3.6.4)
   - InAppSettingsKit (from `git://github.com/fkuehne/InAppSettingsKit.git`, commit
     `415ea6bb`)
-  - MetaDataFetcherKit (~> 0.1.2)
+  - JSAnimatedImagesView (from `git://github.com/fkuehne/JSAnimatedImagesView.git`)
+  - MetaDataFetcherKit (~> 0.1.5)
+  - MSWeakTimer (from `git://github.com/fkuehne/MSWeakTimer.git`)
   - OBSlider (= 1.1.0)
   - RESideMenu (~> 4.0.7)
   - SSKeychain (from `git://github.com/fkuehne/sskeychain.git`)
@@ -47,6 +51,10 @@ EXTERNAL SOURCES:
   InAppSettingsKit:
     :commit: 415ea6bb
     :git: git://github.com/fkuehne/InAppSettingsKit.git
+  JSAnimatedImagesView:
+    :git: git://github.com/fkuehne/JSAnimatedImagesView.git
+  MSWeakTimer:
+    :git: git://github.com/fkuehne/MSWeakTimer.git
   SSKeychain:
     :git: git://github.com/fkuehne/sskeychain.git
 
@@ -60,6 +68,12 @@ CHECKOUT OPTIONS:
   InAppSettingsKit:
     :commit: 415ea6bb
     :git: git://github.com/fkuehne/InAppSettingsKit.git
+  JSAnimatedImagesView:
+    :commit: fd203bc32fedccc4589afb72974b7b1a9edf79f3
+    :git: git://github.com/fkuehne/JSAnimatedImagesView.git
+  MSWeakTimer:
+    :commit: 12a962bf2feaf219a044ccfa06b380f5b3ab26ee
+    :git: git://github.com/fkuehne/MSWeakTimer.git
   SSKeychain:
     :commit: a8e9b21f96adf1ec296e51778ef137f0ea3bd078
     :git: git://github.com/fkuehne/sskeychain.git
@@ -70,7 +84,9 @@ SPEC CHECKSUMS:
   CocoaHTTPServer: 07df8b05a8bde406fe367d22c90a24a2fd4ca49f
   HockeySDK: c07cdd580296737edcd0963e292c19885a53f563
   InAppSettingsKit: 76d5cfbaa3e3f8aa53fe3628516da7eb1aa6a5cb
-  MetaDataFetcherKit: 9bf321e3cc92eeaa45d03fe67b8fcdf178c9e622
+  JSAnimatedImagesView: ad2d21873490d3e675cbe8e49954dfd9495bdcec
+  MetaDataFetcherKit: be17957a9498740bc34329a7e8295e930800884a
+  MSWeakTimer: 08188e0ae3f8eafcc31b95639565543c3c03cda6
   OBSlider: 490f108007bfdd5414a38650b211fe403a95b8a0
   RESideMenu: f24c508404b49c667344c54aba7e590883533958
   SSKeychain: 3f42991739c6c60a9cf1bbd4dff6c0d3694bcf3d

+ 160 - 1
VLC for Apple TV/Playback/VLCFullscreenMovieTVViewController.m

@@ -15,6 +15,8 @@
 #import "VLCIRTVTapGestureRecognizer.h"
 #import "VLCHTTPUploaderController.h"
 #import "VLCSiriRemoteGestureRecognizer.h"
+#import "JSAnimatedImagesView.h"
+#import "MetaDataFetcherKit.h"
 
 typedef NS_ENUM(NSInteger, VLCPlayerScanState)
 {
@@ -26,12 +28,17 @@ typedef NS_ENUM(NSInteger, VLCPlayerScanState)
 @interface VLCFullscreenMovieTVViewController (UIViewControllerTransitioningDelegate) <UIViewControllerTransitioningDelegate, UIGestureRecognizerDelegate>
 @end
 
-@interface VLCFullscreenMovieTVViewController ()
+@interface VLCFullscreenMovieTVViewController () <JSAnimatedImagesViewDataSource, MDFHatchetFetcherDataRecipient>
 
 @property (nonatomic) NSTimer *hidePlaybackControlsViewAfterDeleayTimer;
 @property (nonatomic) VLCPlaybackInfoTVViewController *infoViewController;
 @property (nonatomic) NSNumber *scanSavedPlaybackRate;
 @property (nonatomic) VLCPlayerScanState scanState;
+@property (nonatomic) JSAnimatedImagesView *animatedImageView;
+@property (nonatomic) MDFHatchetFetcher *audioMetaDataFetcher;
+@property (nonatomic) NSString *lastArtist;
+@property (nonatomic) NSMutableArray *audioImagesArray;
+
 @end
 
 @implementation VLCFullscreenMovieTVViewController
@@ -103,6 +110,9 @@ typedef NS_ENUM(NSInteger, VLCPlayerScanState)
     siriArrowRecognizer.delegate = self;
     [self.view addGestureRecognizer:siriArrowRecognizer];
 
+    self.animatedImageView = [[JSAnimatedImagesView alloc] initWithFrame:self.view.frame];
+    self.animatedImageView.dataSource = self;
+    self.animatedImageView.backgroundColor = [UIColor blackColor];
 }
 
 - (void)didReceiveMemoryWarning
@@ -613,6 +623,41 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
                                    audioOnly:(BOOL)audioOnly
 {
     self.titleLabel.text = title;
+
+    if (audioOnly) {
+        if (!self.audioImagesArray)
+            self.audioImagesArray = [NSMutableArray array];
+
+        if (!self.audioMetaDataFetcher) {
+            self.audioMetaDataFetcher = [[MDFHatchetFetcher alloc] init];
+            self.audioMetaDataFetcher.dataRecipient = self;
+        }
+
+        [self.audioMetaDataFetcher cancelAllRequests];
+
+        if (artist != nil && album != nil) {
+            [self.audioMetaDataFetcher searchForAlbum:album ofArtist:artist];
+            APLog(@"Audio-only track meta changed, tracing artist '%@' and album '%@'", artist, album);
+        } else if (artist != nil) {
+            [self.audioMetaDataFetcher searchForArtist:artist];
+            APLog(@"Audio-only track meta changed, tracing artist '%@'", artist);
+        } else if (title != nil) {
+            NSRange deviderRange = [title rangeOfString:@" - "];
+            if (deviderRange.length != 0) { // for radio stations, all we have is "ARTIST - TITLE"
+                title = [title substringToIndex:deviderRange.location];
+            }
+            APLog(@"Audio-only track meta changed, tracing artist '%@'", title);
+            [self.audioMetaDataFetcher searchForArtist:title];
+        }
+        [self performSelectorOnMainThread:@selector(showAnimatedImagesView) withObject:nil waitUntilDone:NO];
+    } else if (self.animatedImageView.superview != nil) {
+        [self.audioMetaDataFetcher cancelAllRequests];
+        [self.animatedImageView stopAnimating];
+        [self.animatedImageView removeFromSuperview];
+        if (self.audioImagesArray) {
+            [self.audioImagesArray removeAllObjects];
+        }
+    }
 }
 
 #pragma mark -
@@ -641,6 +686,120 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
 {
     return YES;
 }
+
+#pragma mark - slide show view data source
+
+- (NSUInteger)animatedImagesNumberOfImages:(JSAnimatedImagesView *)animatedImagesView
+{
+    NSUInteger retValue;
+    @synchronized(self.audioImagesArray) {
+        retValue = self.audioImagesArray.count;
+    }
+    return retValue;
+}
+
+- (UIImage *)animatedImagesView:(JSAnimatedImagesView *)animatedImagesView imageAtIndex:(NSUInteger)index
+{
+    UIImage *retImage;
+    @synchronized(self.audioImagesArray) {
+        if (index < self.audioImagesArray.count) {
+            retImage = self.audioImagesArray[index];
+        }
+    }
+    return retImage;
+}
+
+- (void)showAnimatedImagesView
+{
+    NSUInteger imageCount;
+    @synchronized(self.audioImagesArray) {
+        imageCount = self.audioImagesArray.count;
+    }
+    if (self.animatedImageView.superview == nil && imageCount > 1) {
+        [self.animatedImageView reloadData];
+        self.animatedImageView.frame = self.view.frame;
+        [self.view addSubview:self.animatedImageView];
+    } else if (imageCount > 1) {
+        [self.animatedImageView reloadData];
+        [self.animatedImageView startAnimating];
+    }
+}
+
+#pragma mark - meta data recipient
+- (void)MDFHatchetFetcher:(MDFHatchetFetcher *)aFetcher didFindAlbum:(MDFMusicAlbum *)album forArtistName:(NSString *)artistName
+{
+    if (![self.lastArtist isEqualToString:artistName]) {
+        @synchronized(self.audioImagesArray) {
+            [self.animatedImageView stopAnimating];
+            [self.audioImagesArray removeAllObjects];
+        }
+    }
+    self.lastArtist = artistName;
+
+    NSString *artworkImageURLString = album.artworkImage;
+    if (artworkImageURLString != nil)
+        [self fetchAudioImage:[NSURL URLWithString:artworkImageURLString]];
+
+    NSArray *imageURLStrings = album.largeSizedArtistImages;
+    NSUInteger imageCount = imageURLStrings.count;
+    for (NSUInteger x = 0; x < imageCount; x++)
+        [self fetchAudioImage:[NSURL URLWithString:imageURLStrings[x]]];
+    if (imageCount < 5) {
+        imageURLStrings = album.mediumSizedArtistImages;
+        imageCount = imageURLStrings.count;
+        for (NSUInteger x = 0; x < imageCount; x++)
+            [self fetchAudioImage:[NSURL URLWithString:imageURLStrings[x]]];
+    }
+}
+
+- (void)MDFHatchetFetcher:(MDFHatchetFetcher *)aFetcher didFailToFindAlbum:(NSString *)albumName forArtistName:(NSString *)artistName
+{
+    APLog(@"%s: %@ %@", __PRETTY_FUNCTION__, artistName, albumName);
+}
+
+- (void)MDFHatchetFetcher:(MDFHatchetFetcher *)aFetcher didFindArtist:(MDFArtist *)artist forSearchRequest:(NSString *)searchRequest
+{
+    if (![self.lastArtist isEqualToString:searchRequest]) {
+        @synchronized(self.audioImagesArray) {
+            [self.animatedImageView stopAnimating];
+            [self.audioImagesArray removeAllObjects];
+        }
+    }
+    self.lastArtist = searchRequest;
+    NSArray *imageURLStrings = artist.largeSizedImages;
+    NSUInteger imageCount = imageURLStrings.count;
+    for (NSUInteger x = 0; x < imageCount; x++)
+        [self fetchAudioImage:[NSURL URLWithString:imageURLStrings[x]]];
+    if (imageCount < 4) {
+        imageURLStrings = artist.mediumSizedImages;
+        imageCount = imageURLStrings.count;
+        for (NSUInteger x = 0; x < imageCount; x++)
+            [self fetchAudioImage:[NSURL URLWithString:imageURLStrings[x]]];
+    }
+}
+
+- (void)MDFHatchetFetcher:(MDFHatchetFetcher *)aFetcher didFailToFindArtistForSearchRequest:(NSString *)searchRequest
+{
+    APLog(@"%s: %@", __PRETTY_FUNCTION__, searchRequest);
+}
+
+- (void)fetchAudioImage:(NSURL *)url
+{
+    __weak typeof(self) weakSelf = self;
+    NSURLSession *sharedSession = [NSURLSession sharedSession];
+    NSURLSessionDataTask *task = [sharedSession dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
+        if (!data) {
+            return;
+        }
+        UIImage *image = [UIImage imageWithData:data];
+        @synchronized(weakSelf.audioImagesArray) {
+            [weakSelf.audioImagesArray addObject:image];
+        }
+        [weakSelf performSelectorOnMainThread:@selector(showAnimatedImagesView) withObject:nil waitUntilDone:NO];
+    }];
+    [task resume];
+}
+
 @end