Browse Source

VPC: add ATV support

Felix Paul Kühne 9 years ago
parent
commit
01f8b666e4

+ 2 - 0
Sources/VLCPlaybackController.h

@@ -58,8 +58,10 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
 @property (nonatomic, retain) VLCMediaList *mediaList;
 @property (nonatomic, retain) VLCMediaList *mediaList;
 @property (nonatomic, readwrite) int itemInMediaListToBePlayedFirst;
 @property (nonatomic, readwrite) int itemInMediaListToBePlayedFirst;
 
 
+#if TARGET_OS_IOS
 /* returns nil if currently playing item is not a MLFile, e.g. a url */
 /* returns nil if currently playing item is not a MLFile, e.g. a url */
 @property (nonatomic, strong, readonly) MLFile *currentlyPlayingMediaFile;
 @property (nonatomic, strong, readonly) MLFile *currentlyPlayingMediaFile;
+#endif
 
 
 @property (nonatomic, weak) id<VLCPlaybackControllerDelegate> delegate;
 @property (nonatomic, weak) id<VLCPlaybackControllerDelegate> delegate;
 
 

+ 50 - 36
Sources/VLCPlaybackController.m

@@ -21,10 +21,13 @@
 #import "UIDevice+VLC.h"
 #import "UIDevice+VLC.h"
 #import <AVFoundation/AVFoundation.h>
 #import <AVFoundation/AVFoundation.h>
 #import <MediaPlayer/MediaPlayer.h>
 #import <MediaPlayer/MediaPlayer.h>
+
+#if TARGET_OS_IOS
+#import "VLCKeychainCoordinator.h"
 #import "VLCThumbnailsCache.h"
 #import "VLCThumbnailsCache.h"
-#import <WatchKit/WatchKit.h>
 #import "VLCLibraryViewController.h"
 #import "VLCLibraryViewController.h"
-#import "VLCKeychainCoordinator.h"
+#import <WatchKit/WatchKit.h>
+#endif
 
 
 NSString *const VLCPlaybackControllerPlaybackDidStart = @"VLCPlaybackControllerPlaybackDidStart";
 NSString *const VLCPlaybackControllerPlaybackDidStart = @"VLCPlaybackControllerPlaybackDidStart";
 NSString *const VLCPlaybackControllerPlaybackDidPause = @"VLCPlaybackControllerPlaybackDidPause";
 NSString *const VLCPlaybackControllerPlaybackDidPause = @"VLCPlaybackControllerPlaybackDidPause";
@@ -33,7 +36,7 @@ NSString *const VLCPlaybackControllerPlaybackDidStop = @"VLCPlaybackControllerPl
 NSString *const VLCPlaybackControllerPlaybackMetadataDidChange = @"VLCPlaybackControllerPlaybackMetadataDidChange";
 NSString *const VLCPlaybackControllerPlaybackMetadataDidChange = @"VLCPlaybackControllerPlaybackMetadataDidChange";
 NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPlaybackDidFail";
 NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPlaybackDidFail";
 
 
-@interface VLCPlaybackController () <AVAudioSessionDelegate, VLCMediaPlayerDelegate, VLCMediaDelegate>
+@interface VLCPlaybackController () <VLCMediaPlayerDelegate, VLCMediaDelegate>
 {
 {
     BOOL _playerIsSetup;
     BOOL _playerIsSetup;
     BOOL _playbackFailed;
     BOOL _playbackFailed;
@@ -104,34 +107,10 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
 
 
 #pragma mark - playback management
 #pragma mark - playback management
 
 
-- (BOOL)_blobCheck
-{
-    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
-    NSString *directoryPath = searchPaths[0];
-
-    if (![[NSFileManager defaultManager] fileExistsAtPath:[directoryPath stringByAppendingPathComponent:@"blob.bin"]])
-        return NO;
-
-    NSData *data = [NSData dataWithContentsOfFile:[directoryPath stringByAppendingPathComponent:@"blob.bin"]];
-    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
-    CC_SHA1(data.bytes, (unsigned int)data.length, digest);
-
-    NSMutableString *hash = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
-
-    for (unsigned int u = 0; u < CC_SHA1_DIGEST_LENGTH; u++)
-        [hash appendFormat:@"%02x", digest[u]];
-
-    if ([hash isEqualToString:kBlobHash])
-        return YES;
-    else
-        return NO;
-}
-
-
 - (BOOL)_isMediaSuitableForDevice:(VLCMedia *)media
 - (BOOL)_isMediaSuitableForDevice:(VLCMedia *)media
 {
 {
     NSArray *tracksInfo = media.tracksInformation;
     NSArray *tracksInfo = media.tracksInformation;
-    double width, height = 0;
+    double width = 0.0, height = 0.0;
     NSDictionary *track;
     NSDictionary *track;
     for (NSUInteger x = 0; x < tracksInfo.count; x++) {
     for (NSUInteger x = 0; x < tracksInfo.count; x++) {
         track = tracksInfo[x];
         track = tracksInfo[x];
@@ -212,7 +191,9 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
         return;
         return;
     _activeSession = YES;
     _activeSession = YES;
 
 
+#if TARGET_OS_IOS
     [[AVAudioSession sharedInstance] setDelegate:self];
     [[AVAudioSession sharedInstance] setDelegate:self];
+#endif
 
 
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
 
 
@@ -269,6 +250,7 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
     }
     }
     [_listPlayer setRepeatMode:VLCDoNotRepeat];
     [_listPlayer setRepeatMode:VLCDoNotRepeat];
 
 
+#if TARGET_OS_IOS
     if (![self _isMediaSuitableForDevice:media]) {
     if (![self _isMediaSuitableForDevice:media]) {
         VLCAlertView *alert = [[VLCAlertView alloc] initWithTitle:NSLocalizedString(@"DEVICE_TOOSLOW_TITLE", nil)
         VLCAlertView *alert = [[VLCAlertView alloc] initWithTitle:NSLocalizedString(@"DEVICE_TOOSLOW_TITLE", nil)
                                                           message:[NSString stringWithFormat:NSLocalizedString(@"DEVICE_TOOSLOW", nil), [[UIDevice currentDevice] model], media.url.lastPathComponent]
                                                           message:[NSString stringWithFormat:NSLocalizedString(@"DEVICE_TOOSLOW", nil), [[UIDevice currentDevice] model], media.url.lastPathComponent]
@@ -277,6 +259,7 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
                                                 otherButtonTitles:NSLocalizedString(@"BUTTON_OPEN", nil), nil];
                                                 otherButtonTitles:NSLocalizedString(@"BUTTON_OPEN", nil), nil];
         [alert show];
         [alert show];
     } else
     } else
+#endif
         [self _playNewMedia];
         [self _playNewMedia];
 }
 }
 
 
@@ -310,6 +293,7 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
     [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackDidStart object:self];
     [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackDidStart object:self];
 }
 }
 
 
+#if TARGET_OS_IOS
 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
 {
 {
     if (buttonIndex == 1)
     if (buttonIndex == 1)
@@ -317,6 +301,7 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
     else
     else
         [self stopPlayback];
         [self stopPlayback];
 }
 }
+#endif
 
 
 - (void)stopPlayback
 - (void)stopPlayback
 {
 {
@@ -331,13 +316,9 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
 
 
         if (_mediaPlayer.media) {
         if (_mediaPlayer.media) {
             [_mediaPlayer pause];
             [_mediaPlayer pause];
+#if TARGET_OS_IOS
             [self _savePlaybackState];
             [self _savePlaybackState];
-            @try {
-                [[MLMediaLibrary sharedMediaLibrary] save];
-            }
-            @catch (NSException *exception) {
-                APLog(@"saving playback state failed");
-            }
+#endif
             [_mediaPlayer stop];
             [_mediaPlayer stop];
         }
         }
         if (_mediaPlayer)
         if (_mediaPlayer)
@@ -376,8 +357,16 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
     }
     }
 }
 }
 
 
+#if TARGET_OS_IOS
 - (void)_savePlaybackState
 - (void)_savePlaybackState
 {
 {
+    @try {
+        [[MLMediaLibrary sharedMediaLibrary] save];
+    }
+    @catch (NSException *exception) {
+        APLog(@"saving playback state failed");
+    }
+
     MLFile *fileItem;
     MLFile *fileItem;
     NSArray *files = [MLFile fileForURL:_mediaPlayer.media.url];
     NSArray *files = [MLFile fileForURL:_mediaPlayer.media.url];
     if (files.count > 0)
     if (files.count > 0)
@@ -415,7 +404,9 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
         APLog(@"failed to save current media state - file removed?");
         APLog(@"failed to save current media state - file removed?");
     }
     }
 }
 }
+#endif
 
 
+#if TARGET_OS_IOS
 - (void)_updateStoredThumbnailForFile:(MLFile *)fileItem
 - (void)_updateStoredThumbnailForFile:(MLFile *)fileItem
 {
 {
     NSFileManager *fileManager = [NSFileManager defaultManager];
     NSFileManager *fileManager = [NSFileManager defaultManager];
@@ -449,17 +440,20 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
 
 
     [fileManager removeItemAtPath:newThumbnailPath error:nil];
     [fileManager removeItemAtPath:newThumbnailPath error:nil];
 }
 }
+#endif
 
 
 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 {
 {
     if (_mediaWasJustStarted) {
     if (_mediaWasJustStarted) {
         _mediaWasJustStarted = NO;
         _mediaWasJustStarted = NO;
+#if TARGET_OS_IOS
         if (self.mediaList) {
         if (self.mediaList) {
             MLFile *item;
             MLFile *item;
             NSArray *matches = [MLFile fileForURL:_mediaPlayer.media.url];
             NSArray *matches = [MLFile fileForURL:_mediaPlayer.media.url];
             item = matches.firstObject;
             item = matches.firstObject;
             [self _recoverLastPlaybackStateOfItem:item];
             [self _recoverLastPlaybackStateOfItem:item];
         }
         }
+#endif
     }
     }
 
 
     if ([self.delegate respondsToSelector:@selector(playbackPositionUpdated:)])
     if ([self.delegate respondsToSelector:@selector(playbackPositionUpdated:)])
@@ -574,7 +568,9 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
 {
 {
     if ([_mediaPlayer isPlaying]) {
     if ([_mediaPlayer isPlaying]) {
         [_listPlayer pause];
         [_listPlayer pause];
+#if TARGET_OS_IOS
         [self _savePlaybackState];
         [self _savePlaybackState];
+#endif
         [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackDidPause object:self];
         [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackDidPause object:self];
     } else {
     } else {
         [_listPlayer play];
         [_listPlayer play];
@@ -743,7 +739,9 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
 
 
     if (![portName isEqualToString:@"Headphones"] && [_mediaPlayer isPlaying]) {
     if (![portName isEqualToString:@"Headphones"] && [_mediaPlayer isPlaying]) {
         [_mediaPlayer pause];
         [_mediaPlayer pause];
+#if TARGET_OS_IOS
         [self _savePlaybackState];
         [self _savePlaybackState];
+#endif
         [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackDidPause object:self];
         [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackDidPause object:self];
     }
     }
 }
 }
@@ -764,6 +762,7 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
     _playerIsSetup = NO;
     _playerIsSetup = NO;
 }
 }
 
 
+#if TARGET_OS_IOS
 - (MLFile *)currentlyPlayingMediaFile {
 - (MLFile *)currentlyPlayingMediaFile {
     if (self.mediaList) {
     if (self.mediaList) {
         NSArray *results = [MLFile fileForURL:_mediaPlayer.media.url];
         NSArray *results = [MLFile fileForURL:_mediaPlayer.media.url];
@@ -772,6 +771,7 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
 
 
     return nil;
     return nil;
 }
 }
+#endif
 
 
 #pragma mark - metadata handling
 #pragma mark - metadata handling
 - (void)mediaDidFinishParsing:(VLCMedia *)aMedia
 - (void)mediaDidFinishParsing:(VLCMedia *)aMedia
@@ -798,7 +798,6 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
 {
 {
     _needsMetadataUpdate = NO;
     _needsMetadataUpdate = NO;
 
 
-    MLFile *item;
     NSNumber *trackNumber;
     NSNumber *trackNumber;
 
 
     NSString *title;
     NSString *title;
@@ -807,6 +806,9 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
     UIImage* artworkImage;
     UIImage* artworkImage;
     BOOL mediaIsAudioOnly = NO;
     BOOL mediaIsAudioOnly = NO;
 
 
+#if TARGET_OS_IOS
+    MLFile *item;
+
     if (self.mediaList) {
     if (self.mediaList) {
         NSArray *matches = [MLFile fileForURL:_mediaPlayer.media.url];
         NSArray *matches = [MLFile fileForURL:_mediaPlayer.media.url];
         item = matches.firstObject;
         item = matches.firstObject;
@@ -823,6 +825,7 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
         /* MLKit knows better than us if this thing is audio only or not */
         /* MLKit knows better than us if this thing is audio only or not */
         mediaIsAudioOnly = [item isSupportedAudioFile];
         mediaIsAudioOnly = [item isSupportedAudioFile];
     } else {
     } else {
+#endif
         NSDictionary * metaDict = _mediaPlayer.media.metaDictionary;
         NSDictionary * metaDict = _mediaPlayer.media.metaDictionary;
 
 
         if (metaDict) {
         if (metaDict) {
@@ -831,7 +834,9 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
             albumName = metaDict[VLCMetaInformationAlbum];
             albumName = metaDict[VLCMetaInformationAlbum];
             trackNumber = metaDict[VLCMetaInformationTrackNumber];
             trackNumber = metaDict[VLCMetaInformationTrackNumber];
         }
         }
+#if TARGET_OS_IOS
     }
     }
+#endif
 
 
     if (!mediaIsAudioOnly) {
     if (!mediaIsAudioOnly) {
         /* either what we are playing is not a file known to MLKit or
         /* either what we are playing is not a file known to MLKit or
@@ -849,6 +854,7 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
     }
     }
 
 
     if (mediaIsAudioOnly) {
     if (mediaIsAudioOnly) {
+#if TARGET_OS_IOS
         artworkImage = [VLCThumbnailsCache thumbnailForManagedObject:item];
         artworkImage = [VLCThumbnailsCache thumbnailForManagedObject:item];
 
 
         if (artworkImage) {
         if (artworkImage) {
@@ -857,6 +863,7 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
             if (albumName)
             if (albumName)
                 title = [title stringByAppendingFormat:@" — %@", albumName];
                 title = [title stringByAppendingFormat:@" — %@", albumName];
         }
         }
+#endif
 
 
         if (title.length < 1)
         if (title.length < 1)
             title = [[_mediaPlayer.media url] lastPathComponent];
             title = [[_mediaPlayer.media url] lastPathComponent];
@@ -878,7 +885,9 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
     currentlyPlayingTrackInfo[MPNowPlayingInfoPropertyPlaybackRate] = @(_mediaPlayer.isPlaying ? _mediaPlayer.rate : 0.0);
     currentlyPlayingTrackInfo[MPNowPlayingInfoPropertyPlaybackRate] = @(_mediaPlayer.isPlaying ? _mediaPlayer.rate : 0.0);
 
 
     /* don't leak sensitive information to the OS, if passcode lock is enabled */
     /* don't leak sensitive information to the OS, if passcode lock is enabled */
+#if TARGET_OS_IOS
     if (![[VLCKeychainCoordinator defaultCoordinator] passcodeLockEnabled]) {
     if (![[VLCKeychainCoordinator defaultCoordinator] passcodeLockEnabled]) {
+#endif
         if (title)
         if (title)
             currentlyPlayingTrackInfo[MPMediaItemPropertyTitle] = title;
             currentlyPlayingTrackInfo[MPMediaItemPropertyTitle] = title;
         if (artist.length > 0)
         if (artist.length > 0)
@@ -889,6 +898,7 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
         if ([trackNumber intValue] > 0)
         if ([trackNumber intValue] > 0)
             currentlyPlayingTrackInfo[MPMediaItemPropertyAlbumTrackNumber] = trackNumber;
             currentlyPlayingTrackInfo[MPMediaItemPropertyAlbumTrackNumber] = trackNumber;
 
 
+#if TARGET_OS_IOS
         /* FIXME: UGLY HACK
         /* FIXME: UGLY HACK
          * iOS 8.2 and 8.3 include an issue which will lead to a termination of the client app if we set artwork
          * iOS 8.2 and 8.3 include an issue which will lead to a termination of the client app if we set artwork
          * when the playback initialized through the watch extension
          * when the playback initialized through the watch extension
@@ -902,6 +912,7 @@ NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPl
             currentlyPlayingTrackInfo[MPMediaItemPropertyArtwork] = mpartwork;
             currentlyPlayingTrackInfo[MPMediaItemPropertyArtwork] = mpartwork;
         }
         }
     }
     }
+#endif
 
 
 setstuff:
 setstuff:
     [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = currentlyPlayingTrackInfo;
     [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = currentlyPlayingTrackInfo;
@@ -912,9 +923,9 @@ setstuff:
     _albumName = albumName;
     _albumName = albumName;
     _artworkImage = artworkImage;
     _artworkImage = artworkImage;
     _mediaIsAudioOnly = mediaIsAudioOnly;
     _mediaIsAudioOnly = mediaIsAudioOnly;
-
 }
 }
 
 
+#if TARGET_OS_IOS
 - (void)_recoverLastPlaybackStateOfItem:(MLFile *)item
 - (void)_recoverLastPlaybackStateOfItem:(MLFile *)item
 {
 {
     if (item) {
     if (item) {
@@ -959,6 +970,7 @@ setstuff:
         }
         }
     }
     }
 }
 }
+#endif
 
 
 - (void)recoverDisplayedMetadata
 - (void)recoverDisplayedMetadata
 {
 {
@@ -1151,7 +1163,9 @@ static inline NSArray * RemoteCommandCenterCommandsToHandle(MPRemoteCommandCente
 
 
 - (void)applicationWillResignActive:(NSNotification *)aNotification
 - (void)applicationWillResignActive:(NSNotification *)aNotification
 {
 {
+#if TARGET_OS_IOS
     [self _savePlaybackState];
     [self _savePlaybackState];
+#endif
 
 
     if (![[[NSUserDefaults standardUserDefaults] objectForKey:kVLCSettingContinueAudioInBackgroundKey] boolValue]) {
     if (![[[NSUserDefaults standardUserDefaults] objectForKey:kVLCSettingContinueAudioInBackgroundKey] boolValue]) {
         if ([_mediaPlayer isPlaying]) {
         if ([_mediaPlayer isPlaying]) {

+ 2 - 0
VLC for iOS.xcodeproj/project.pbxproj

@@ -142,6 +142,7 @@
 		7D74177A1AE2D3CE001F1997 /* VLCNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D7417791AE2D3CE001F1997 /* VLCNavigationController.m */; };
 		7D74177A1AE2D3CE001F1997 /* VLCNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D7417791AE2D3CE001F1997 /* VLCNavigationController.m */; };
 		7D7EF3DA1BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EF3D81BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.m */; };
 		7D7EF3DA1BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EF3D81BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.m */; };
 		7D7EF3DB1BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D7EF3D91BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.xib */; };
 		7D7EF3DB1BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D7EF3D91BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.xib */; };
+		7D7EF3DD1BD5779F00CD4CEE /* VLCPlaybackController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DE56C191AD93F9100E8CA00 /* VLCPlaybackController.m */; };
 		7D84E4C61B41AB2800EA7D1F /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D84E4C51B41AB2800EA7D1F /* VideoToolbox.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
 		7D84E4C61B41AB2800EA7D1F /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D84E4C51B41AB2800EA7D1F /* VideoToolbox.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
 		7D84E4C91B41ABCE00EA7D1F /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D84E4C81B41ABCE00EA7D1F /* CoreMedia.framework */; };
 		7D84E4C91B41ABCE00EA7D1F /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D84E4C81B41ABCE00EA7D1F /* CoreMedia.framework */; };
 		7D8968711BD3058800F4EAAD /* LocalAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D8968701BD3058800F4EAAD /* LocalAuthentication.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
 		7D8968711BD3058800F4EAAD /* LocalAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D8968701BD3058800F4EAAD /* LocalAuthentication.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
@@ -2181,6 +2182,7 @@
 			files = (
 			files = (
 				7DC71D211BC83058001FACAA /* VLCAppSharesTVViewController.m in Sources */,
 				7DC71D211BC83058001FACAA /* VLCAppSharesTVViewController.m in Sources */,
 				7D7EF3DA1BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.m in Sources */,
 				7D7EF3DA1BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.m in Sources */,
+				7D7EF3DD1BD5779F00CD4CEE /* VLCPlaybackController.m in Sources */,
 				7DC71D261BC830A5001FACAA /* VLCLocalNetworkTVViewController.m in Sources */,
 				7DC71D261BC830A5001FACAA /* VLCLocalNetworkTVViewController.m in Sources */,
 				7D1329441BA1F10100BE647E /* AppDelegate.m in Sources */,
 				7D1329441BA1F10100BE647E /* AppDelegate.m in Sources */,
 				7D1329411BA1F10100BE647E /* main.m in Sources */,
 				7D1329411BA1F10100BE647E /* main.m in Sources */,