浏览代码

Introduce new VLCPlayerDisplayController class which is responsible to show/hide the full screen and mini player
remove playback view related stuff from VLCAppDelegate and VLCPlaylistViewController
add notifications for playback state changes, so more objects than just the VLCPlaybackControllerDelegate can react to playback state and meta data changes

(cherry picked from commit aa52c9a192f57a6c084477ac2097e7426792b980)

Tobias Conradi 10 年之前
父节点
当前提交
32afeec2d1

+ 3 - 1
Sources/VLCAppDelegate.h

@@ -21,6 +21,7 @@
 #import "VLCDownloadViewController.h"
 
 @class VLCPlaylistViewController;
+@class VLCPlayerDisplayController;
 @interface VLCAppDelegate : UIResponder <UIApplicationDelegate>
 
 - (void)updateMediaList;
@@ -33,7 +34,6 @@
 
 - (void)cleanCache;
 
-- (void)presentMovieViewControllerAnimated:(BOOL)animated;
 - (void)openMediaFromManagedObject:(NSManagedObject *)file;
 - (void)openMovieFromURL:(NSURL *)url;
 - (void)openMovieWithExternalSubtitleFromURL:(NSURL *)url externalSubURL:(NSString *)SubtitlePath;
@@ -42,6 +42,8 @@
 @property (nonatomic, readonly) VLCDropboxTableViewController *dropboxTableViewController;
 @property (nonatomic, readonly) VLCDownloadViewController *downloadViewController;
 
+@property (nonatomic, readonly) VLCPlayerDisplayController *playerDisplayController;
+
 @property (nonatomic, strong) UIWindow *window;
 
 @property (nonatomic, strong) GHRevealViewController *revealController;

+ 6 - 45
Sources/VLCAppDelegate.m

@@ -21,7 +21,6 @@
 #import "NSString+SupportedMedia.h"
 #import "UIDevice+VLC.h"
 #import "VLCPlaylistViewController.h"
-#import "VLCMovieViewController.h"
 #import "VLCPlaybackNavigationController.h"
 #import "PAPasscodeViewController.h"
 #import "VLCHTTPUploaderController.h"
@@ -34,6 +33,7 @@
 #import "VLCNavigationController.h"
 #import "VLCWatchMessage.h"
 #import "VLCPlaybackController+MediaLibrary.h"
+#import "VLCPlayerDisplayController.h"
 
 #define HAVE_FABRIC 0
 
@@ -51,11 +51,8 @@
     BOOL _passcodeValidated;
     BOOL _isRunningMigration;
     BOOL _isComingFromHandoff;
-    BOOL _presentingMovieController;
 }
 
-@property (nonatomic, strong) VLCMovieViewController *movieViewController;
-
 @end
 
 @implementation VLCAppDelegate
@@ -126,7 +123,10 @@
         _revealController.sidebarViewController = _menuViewController;
         _revealController.contentViewController = navCon;
 
-        self.window.rootViewController = self.revealController;
+         _playerDisplayController = [[VLCPlayerDisplayController alloc] init];
+         _playerDisplayController.childViewController = self.revealController;
+
+        self.window.rootViewController = _playerDisplayController;
         // necessary to avoid navbar blinking in VLCOpenNetworkStreamViewController & VLCDownloadViewController
         _revealController.contentViewController.view.backgroundColor = [UIColor VLCDarkBackgroundColor];
         [self.window makeKeyAndVisible];
@@ -169,7 +169,7 @@
 
     [[VLCNotificationRelay sharedRelay] addRelayLocalName:NSManagedObjectContextDidSaveNotification toRemoteName:@"org.videolan.ios-app.dbupdate"];
 
-    [[VLCNotificationRelay sharedRelay] addRelayLocalName:kVLCNotificationNowPlayingInfoUpdate toRemoteName:kVLCDarwinNotificationNowPlayingInfoUpdate];
+    [[VLCNotificationRelay sharedRelay] addRelayLocalName:VLCPlaybackControllerPlaybackMetadataDidChange toRemoteName:kVLCDarwinNotificationNowPlayingInfoUpdate];
 
 #if HAVE_FABRIC
     [Fabric with:@[CrashlyticsKit]];
@@ -317,10 +317,6 @@ continueUserActivity:(NSUserActivity *)userActivity
 
 - (void)applicationWillResignActive:(UIApplication *)application
 {
-    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
-    _presentingMovieController = vpc.presentingMovieViewController;
-    [vpc destroyCurrentViewController];
-
     _passcodeValidated = NO;
     [self validatePasscode];
     [[MLMediaLibrary sharedMediaLibrary] applicationWillExit];
@@ -334,12 +330,6 @@ continueUserActivity:(NSUserActivity *)userActivity
     } else if(_isComingFromHandoff) {
         _isComingFromHandoff = NO;
     }
-
-    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
-    if (!vpc.audioOnlyPlaybackSession && _presentingMovieController)
-        [self presentMovieViewControllerAnimated:NO];
-    else
-        [self.playlistViewController displayMiniPlaybackViewIfNeeded];
 }
 
 - (void)applicationWillTerminate:(UIApplication *)application
@@ -369,14 +359,6 @@ continueUserActivity:(NSUserActivity *)userActivity
     return _downloadViewController;
 }
 
-- (VLCMovieViewController *)movieViewController
-{
-    if (!_movieViewController) {
-        _movieViewController = [[VLCMovieViewController alloc] initWithNibName:nil bundle:nil];
-        [VLCPlaybackController sharedInstance].delegate = _movieViewController;
-    }
-    return _movieViewController;
-}
 
 #pragma mark - media discovering
 
@@ -557,31 +539,10 @@ continueUserActivity:(NSUserActivity *)userActivity
 
 #pragma mark - playback view handling
 
-- (void)presentMovieViewControllerAnimated:(BOOL)animated
-{
-    if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
-        return;
-    }
-
-    UINavigationController *navCon = [[VLCPlaybackNavigationController alloc] initWithRootViewController:self.movieViewController];
-    [self.movieViewController prepareForMediaPlayback:[VLCPlaybackController sharedInstance]];
-    navCon.modalPresentationStyle = UIModalPresentationFullScreen;
-    [self.window.rootViewController presentViewController:navCon animated:animated completion:nil];
-}
-
 - (void)openMediaFromManagedObject:(NSManagedObject *)mediaObject
 {
-    BOOL retainFullscreenPlayback = false;
-
     VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
-
-    if (vpc.presentingMovieViewController)
-        retainFullscreenPlayback = YES;
-
     [vpc playMediaLibraryObject:mediaObject];
-
-    if (retainFullscreenPlayback)
-        [self presentMovieViewControllerAnimated:YES];
 }
 
 - (void)openMovieFromURL:(NSURL *)url

+ 0 - 2
Sources/VLCConstants.h

@@ -81,8 +81,6 @@
 
 #define kBlobHash @"521923d214b9ae628da7987cf621e94c4afdd726"
 
-
-#define kVLCNotificationNowPlayingInfoUpdate @"nowPlayingInfoUpdate"
 #define kVLCDarwinNotificationNowPlayingInfoUpdate @"org.videolan.ios-app.nowPlayingInfoUpdate"
 
 #if TARGET_IPHONE_SIMULATOR

+ 2 - 1
Sources/VLCMiniPlaybackView.h

@@ -12,9 +12,10 @@
 
 #import "VLCFrostedGlasView.h"
 
+@class VLCPlaybackController;
 @interface VLCMiniPlaybackView : VLCFrostedGlasView
 // just a state keeper for animation, has no other implementation
 @property (nonatomic) BOOL visible;
-- (void)setupForWork;
 
+- (void)setupForWork:(VLCPlaybackController *)playbackController;
 @end

+ 8 - 23
Sources/VLCMiniPlaybackView.m

@@ -25,6 +25,7 @@
     UIButton *_expandButton;
     UILabel *_metaDataLabel;
 }
+@property (nonatomic, weak) VLCPlaybackController *playbackController;
 
 @end
 
@@ -90,30 +91,27 @@
 
 - (void)previousAction:(id)sender
 {
-    [[VLCPlaybackController sharedInstance] backward];
+    [self.playbackController backward];
 }
 
 - (void)playPauseAction:(id)sender
 {
-    [[VLCPlaybackController sharedInstance] playPause];
+    [self.playbackController playPause];
 }
 
 - (void)nextAction:(id)sender
 {
-    [[VLCPlaybackController sharedInstance] forward];
+    [self.playbackController forward];
 }
 
 - (void)pushFullPlaybackView:(id)sender
 {
-    [VLCPlaybackController sharedInstance].videoOutputView = nil;
-
-    VLCAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
-    [appDelegate presentMovieViewControllerAnimated:YES];
+    [[UIApplication sharedApplication] sendAction:@selector(showFullscreenPlayback) to:nil from:self forEvent:nil];
 }
 
-- (void)setupForWork
+- (void)setupForWork:(VLCPlaybackController *)playbackController
 {
-    VLCPlaybackController *playbackController = [VLCPlaybackController sharedInstance];
+    self.playbackController = playbackController;
     if (playbackController.isPlaying)
         [_playPauseButton setImage:[UIImage imageNamed:@"pauseIcon"] forState:UIControlStateNormal];
     else
@@ -155,9 +153,7 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
         _videoView = [[UIView alloc] initWithFrame:_artworkView.frame];
         [_videoView setClipsToBounds:YES];
         [self addSubview:_videoView];
-
-        if (!controller.presentingMovieViewController)
-            controller.videoOutputView = _videoView;
+        controller.videoOutputView = _videoView;
     }
 
     NSString *metaDataString;
@@ -173,15 +169,4 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
     _metaDataLabel.text = metaDataString;
 }
 
-- (void)presentingViewControllerShouldBeClosed:(VLCPlaybackController *)controller
-{
-    VLCAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
-    [appDelegate.playlistViewController displayMiniPlaybackViewIfNeeded];
-}
-
-- (void)presentingViewControllerShouldBeClosedAfterADelay:(VLCPlaybackController *)controller
-{
-    [self presentingViewControllerShouldBeClosed:controller];
-}
-
 @end

+ 3 - 0
Sources/VLCMovieViewController.h

@@ -116,4 +116,7 @@
 
 - (BOOL)rotationIsDisabled;
 
+- (void)setControlsHidden:(BOOL)hidden animated:(BOOL)animated;
+- (void)showStatusMessage:(NSString *)statusMessage;
+
 @end

+ 17 - 18
Sources/VLCMovieViewController.m

@@ -416,6 +416,8 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
 
         [self.view addSubview:_sleepTimerContainer];
     }
+
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidStop:) name:VLCPlaybackControllerPlaybackDidStop object:nil];
 }
 
 - (void)viewWillAppear:(BOOL)animated
@@ -440,7 +442,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
 
     VLCPlaybackController *vpc = self.playbackController;
     vpc.delegate = self;
-    vpc.presentingMovieViewController = YES;
     [vpc recoverPlaybackState];
 
     [self setControlsHidden:NO animated:YES];
@@ -500,8 +501,9 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
 - (void)viewWillDisappear:(BOOL)animated
 {
     VLCPlaybackController *vpc = self.playbackController;
-    vpc.videoOutputView = nil;
-    vpc.presentingMovieViewController = NO;
+    if (vpc.videoOutputView == self.movieView) {
+        vpc.videoOutputView = nil;
+    }
 
     _viewAppeared = NO;
     if (_idleTimer) {
@@ -685,10 +687,9 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
 - (IBAction)closePlayback:(id)sender
 {
     LOCKCHECK;
+    [[UIApplication sharedApplication] sendAction:@selector(closeFullscreenPlayback) to:nil from:self forEvent:nil];
 
-    [self presentingViewControllerShouldBeClosed:nil];
 }
-
 - (IBAction)positionSliderAction:(UISlider *)sender
 {
     LOCKCHECK;
@@ -811,15 +812,9 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
     [self _resetIdleTimer];
 }
 
-- (void)presentingViewControllerShouldBeClosed:(VLCPlaybackController *)controller
-{
-    [self setControlsHidden:NO animated:NO];
-    [self.navigationController dismissViewControllerAnimated:YES completion:nil];
-}
-
-- (void)presentingViewControllerShouldBeClosedAfterADelay:(VLCPlaybackController *)controller
+- (void)playbackDidStop:(NSNotification *)notification
 {
-    [self performSelector:@selector(presentingViewControllerShouldBeClosed:) withObject:nil afterDelay:2.];
+    [self closePlayback:nil];
 }
 
 - (void)mediaPlayerStateChanged:(VLCMediaPlayerState)currentState
@@ -854,7 +849,7 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
 
 - (void)showStatusMessage:(NSString *)statusMessage forPlaybackController:(VLCPlaybackController *)controller
 {
-    [self.statusLabel showStatusMessage:statusMessage];
+    [self showStatusMessage:statusMessage];
 }
 
 - (void)displayMetadataForPlaybackController:(VLCPlaybackController *)controller
@@ -1014,15 +1009,19 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
     [self _resetIdleTimer];
 }
 
+- (void)showStatusMessage:(NSString *)statusMessage
+{
+    [self.statusLabel showStatusMessage:statusMessage];
+}
+
 #pragma mark - multi-select delegation
 
 - (void)toggleUILock
 {
     _interfaceIsLocked = !_interfaceIsLocked;
-    if (_interfaceIsLocked)
-        _multiSelectionView.displayLock = YES;
-    else
-        _multiSelectionView.displayLock = NO;
+
+    _multiSelectionView.displayLock = _interfaceIsLocked;
+    self.backButton.enabled = !_interfaceIsLocked;
 }
 
 - (void)toggleEqualizer

+ 7 - 4
Sources/VLCPlaybackController.h

@@ -13,6 +13,13 @@
 
 #import "VLCEqualizerView.h"
 
+extern NSString *const VLCPlaybackControllerPlaybackDidStart;
+extern NSString *const VLCPlaybackControllerPlaybackDidPause;
+extern NSString *const VLCPlaybackControllerPlaybackDidResume;
+extern NSString *const VLCPlaybackControllerPlaybackDidStop;
+extern NSString *const VLCPlaybackControllerPlaybackDidFail;
+extern NSString *const VLCPlaybackControllerPlaybackMetadataDidChange;
+
 @class VLCPlaybackController;
 
 @protocol VLCPlaybackControllerDelegate <NSObject>
@@ -24,8 +31,6 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
         currentMediaHasChapters:(BOOL)currentMediaHasChapters
           forPlaybackController:(VLCPlaybackController *)controller;
 - (void)prepareForMediaPlayback:(VLCPlaybackController *)controller;
-- (void)presentingViewControllerShouldBeClosed:(VLCPlaybackController *)controller;
-- (void)presentingViewControllerShouldBeClosedAfterADelay:(VLCPlaybackController *)controller;
 - (void)showStatusMessage:(NSString *)statusMessage forPlaybackController:(VLCPlaybackController *)controller;
 - (void)displayMetadataForPlaybackController:(VLCPlaybackController *)controller
                                        title:(NSString *)title
@@ -68,7 +73,6 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
 @property (nonatomic, readonly) BOOL currentMediaHasTrackToChooseFrom;
 @property (nonatomic, readonly) BOOL activePlaybackSession;
 @property (nonatomic, readonly) BOOL audioOnlyPlaybackSession;
-@property (nonatomic, readwrite) BOOL presentingMovieViewController;
 
 + (VLCPlaybackController *)sharedInstance;
 
@@ -85,6 +89,5 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
 
 - (void)setNeedsMetadataUpdate;
 
-- (void)destroyCurrentViewController;
 
 @end

+ 29 - 23
Sources/VLCPlaybackController.m

@@ -23,9 +23,15 @@
 #import <MediaPlayer/MediaPlayer.h>
 #import "VLCThumbnailsCache.h"
 #import <WatchKit/WatchKit.h>
-#import "VLCAppDelegate.h"
 #import "VLCPlaylistViewController.h"
 
+NSString *const VLCPlaybackControllerPlaybackDidStart = @"VLCPlaybackControllerPlaybackDidStart";
+NSString *const VLCPlaybackControllerPlaybackDidPause = @"VLCPlaybackControllerPlaybackDidPause";
+NSString *const VLCPlaybackControllerPlaybackDidResume = @"VLCPlaybackControllerPlaybackDidResume";
+NSString *const VLCPlaybackControllerPlaybackDidStop = @"VLCPlaybackControllerPlaybackDidStop";
+NSString *const VLCPlaybackControllerPlaybackMetadataDidChange = @"VLCPlaybackControllerPlaybackMetadataDidChange";
+NSString *const VLCPlaybackControllerPlaybackDidFail = @"VLCPlaybackControllerPlaybackDidFail";
+
 @interface VLCPlaybackController () <AVAudioSessionDelegate, VLCMediaPlayerDelegate, VLCMediaDelegate>
 {
     BOOL _playerIsSetup;
@@ -303,10 +309,10 @@
 
     [self subscribeRemoteCommands];
 
-    [[(VLCAppDelegate *)[UIApplication sharedApplication].delegate playlistViewController] displayMiniPlaybackViewIfNeeded];
-
     _playerIsSetup = YES;
     _mediaWasJustStarted = YES;
+
+    [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackDidStart object:self];
 }
 
 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
@@ -357,10 +363,14 @@
     else if (self.successCallback)
         [[UIApplication sharedApplication] openURL:self.successCallback];
 
-    [self destroyCurrentViewController];
-
     [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = nil;
     [self unsubscribeFromRemoteCommand];
+
+    if (_playbackFailed) {
+        [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackDidFail object:self];
+    } else {
+        [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackDidStop object:self];
+    }
 }
 
 - (void)_savePlaybackState
@@ -517,6 +527,7 @@
 - (void)mediaPlayerStateChanged:(NSNotification *)aNotification
 {
     VLCMediaPlayerState currentState = _mediaPlayer.state;
+
     if (currentState == VLCMediaPlayerStateBuffering) {
         /* attach delegate */
         _mediaPlayer.media.delegate = self;
@@ -527,21 +538,18 @@
         [_mediaPlayer performSelector:@selector(setTextRendererFontColor:) withObject:[[NSUserDefaults standardUserDefaults] objectForKey:kVLCSettingSubtitlesFontColor]];
     } else if (currentState == VLCMediaPlayerStateError) {
         _playbackFailed = YES;
-        if ([self.delegate respondsToSelector:@selector(presentingViewControllerShouldBeClosedAfterADelay:)])
-            [self.delegate presentingViewControllerShouldBeClosedAfterADelay:self];
         [self stopPlayback];
     } else if ((currentState == VLCMediaPlayerStateEnded || currentState == VLCMediaPlayerStateStopped) && _listPlayer.repeatMode == VLCDoNotRepeat) {
         if ([_listPlayer.mediaList indexOfMedia:_mediaPlayer.media] == _listPlayer.mediaList.count - 1) {
-            [self destroyCurrentViewController];
             [self stopPlayback];
             return;
         }
-    } else {
-        /* disable video decoding if we have no place to show */
-        if (_mediaPlayer.numberOfAudioTracks > 0) {
-            if (_videoOutputViewWrapper == nil)
-                _mediaPlayer.currentVideoTrackIndex = -1;
-        }
+    }
+
+    /* disable video decoding if we have no place to show */
+    if (_mediaPlayer.numberOfAudioTracks > 0) {
+        if (_videoOutputViewWrapper == nil)
+            _mediaPlayer.currentVideoTrackIndex = -1;
     }
 
     if ([self.delegate respondsToSelector:@selector(mediaPlayerStateChanged:isPlaying:currentMediaHasTrackToChooseFrom:currentMediaHasChapters:forPlaybackController:)])
@@ -560,14 +568,18 @@
     if ([_mediaPlayer isPlaying]) {
         [_listPlayer pause];
         [self _savePlaybackState];
-    } else
+        [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackDidPause object:self];
+    } else {
         [_listPlayer play];
+        [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackDidResume object:self];
+    }
 }
 
 - (void)forward
 {
     if (_mediaList) {
         [_listPlayer next];
+        [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackMetadataDidChange object:self];
     } else {
         NSNumber *skipLength = [[NSUserDefaults standardUserDefaults] valueForKey:kVLCSettingPlaybackForwardSkipLength];
         [_mediaPlayer jumpForward:skipLength.intValue];
@@ -578,6 +590,7 @@
 {
     if (_mediaList) {
         [_listPlayer previous];
+        [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackMetadataDidChange object:self];
     }
     else {
         NSNumber *skipLength = [[NSUserDefaults standardUserDefaults] valueForKey:kVLCSettingPlaybackBackwardSkipLength];
@@ -780,12 +793,6 @@
     }
 }
 
-- (void)destroyCurrentViewController
-{
-    if ([self.delegate respondsToSelector:@selector(presentingViewControllerShouldBeClosed:)])
-        [self.delegate presentingViewControllerShouldBeClosed:self];
-}
-
 - (void)_updateDisplayedMetadata
 {
     _needsMetadataUpdate = NO;
@@ -856,7 +863,6 @@
             title = [[_mediaPlayer.media url] lastPathComponent];
     } else if (_mediaWasJustStarted) {
         _mediaWasJustStarted = NO;
-        [(VLCAppDelegate *)[UIApplication sharedApplication].delegate presentMovieViewControllerAnimated:YES];
 
         if (item) {
             if (_mediaPlayer.numberOfAudioTracks > 2) {
@@ -913,7 +919,7 @@
 
 setstuff:
     [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = currentlyPlayingTrackInfo;
-    [[NSNotificationCenter defaultCenter] postNotificationName:kVLCNotificationNowPlayingInfoUpdate object:self];
+    [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlaybackControllerPlaybackMetadataDidChange object:self];
 
     _title = title;
     _artist = artist;

+ 32 - 0
Sources/VLCPlayerDisplayController.h

@@ -0,0 +1,32 @@
+/*****************************************************************************
+ * VLCPlayerDisplayController.h
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2015 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Tobias Conradi <videolan # tobias-conradi.de>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+
+#import <Foundation/Foundation.h>
+
+@class VLCPlaybackController;
+
+typedef NS_ENUM(NSUInteger, VLCPlayerDisplayControllerDisplayMode) {
+    VLCPlayerDisplayControllerDisplayModeFullscreen,
+    VLCPlayerDisplayControllerDisplayModeMiniplayer,
+};
+
+@interface VLCPlayerDisplayController : UIViewController
+@property (nonatomic, strong) UIViewController *childViewController;
+
+@property (nonatomic, assign) VLCPlayerDisplayControllerDisplayMode displayMode;
+@property (nonatomic, weak) VLCPlaybackController *playbackController;
+
+- (void)showFullscreenPlayback;
+- (void)closeFullscreenPlayback;
+
+@end

+ 306 - 0
Sources/VLCPlayerDisplayController.m

@@ -0,0 +1,306 @@
+/*****************************************************************************
+ * VLCPlayerDisplayController.m
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2015 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Tobias Conradi <videolan # tobias-conradi.de>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import "VLCPlayerDisplayController.h"
+#import "VLCPlaybackController.h"
+#import "VLCPlaybackNavigationController.h"
+#import "VLCMovieViewController.h"
+#import "VLCMiniPlaybackView.h"
+
+static NSString *const VLCPlayerDisplayControllerDisplayModeKey = @"VLCPlayerDisplayControllerDisplayMode";
+
+@interface VLCPlayerDisplayController ()
+@property (nonatomic, strong) VLCMovieViewController *movieViewController;
+@property (nonatomic, strong) VLCMiniPlaybackView *miniPlaybackView;
+@end
+
+@implementation VLCPlayerDisplayController
+
++ (void)initialize
+{
+    [[NSUserDefaults standardUserDefaults] registerDefaults:
+  @{
+    VLCPlayerDisplayControllerDisplayModeKey : @(VLCPlayerDisplayControllerDisplayModeFullscreen),
+    }];
+}
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+    }
+    return self;
+}
+static inline void commonSetup(VLCPlayerDisplayController *self)
+{
+    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+    [notificationCenter addObserver:self selector:@selector(playbackDidStart:) name:VLCPlaybackControllerPlaybackDidStart object:nil];
+    [notificationCenter addObserver:self selector:@selector(playbackDidFail:) name:VLCPlaybackControllerPlaybackDidFail object:nil];
+    [notificationCenter addObserver:self selector:@selector(playbackDidStop:) name:VLCPlaybackControllerPlaybackDidStop object:nil];
+
+}
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if (self) {
+        commonSetup(self);
+    }
+    return self;
+}
+- (void)awakeFromNib
+{
+    [super awakeFromNib];
+    commonSetup(self);
+}
+
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    [self setupChildViewController];
+}
+
+#pragma mark - ChildViewController
+
+- (void)setChildViewController:(UIViewController *)childViewController
+{
+    if (_childViewController) {
+        [_childViewController willMoveToParentViewController:nil];
+        [_childViewController.view removeFromSuperview];
+        [_childViewController removeFromParentViewController];
+    }
+    _childViewController = childViewController;
+    if (self.isViewLoaded) {
+        [self setupChildViewController];
+    }
+}
+
+- (void)setupChildViewController
+{
+    UIViewController *childViewController = self.childViewController;
+    [self addChildViewController:childViewController];
+    [self.view addSubview:childViewController.view];
+    [childViewController didMoveToParentViewController:self];
+}
+
+#pragma mark - properties
+
+- (VLCPlayerDisplayControllerDisplayMode)displayMode
+{
+    return [[NSUserDefaults standardUserDefaults] integerForKey:VLCPlayerDisplayControllerDisplayModeKey];
+}
+
+- (void)setDisplayMode:(VLCPlayerDisplayControllerDisplayMode)displayMode
+{
+    [[NSUserDefaults standardUserDefaults] setInteger:displayMode forKey:VLCPlayerDisplayControllerDisplayModeKey];
+}
+
+- (VLCPlaybackController *)playbackController {
+    if (_playbackController == nil) {
+        _playbackController = [VLCPlaybackController sharedInstance];
+    }
+    return _playbackController;
+}
+
+- (VLCMovieViewController *)movieViewController
+{
+    if (!_movieViewController) {
+        _movieViewController = [[VLCMovieViewController alloc] initWithNibName:nil bundle:nil];
+        [VLCPlaybackController sharedInstance].delegate = _movieViewController;
+    }
+    return _movieViewController;
+}
+
+
+
+#pragma mark - Notification Handling
+
+- (void)playbackDidStart:(NSNotification *)notification
+{
+    switch (self.displayMode) {
+        case VLCPlayerDisplayControllerDisplayModeFullscreen:
+            [self _presentFullscreenPlaybackViewIfNeeded];
+            break;
+        case VLCPlayerDisplayControllerDisplayModeMiniplayer:
+            [self _showHideMiniPlaybackView];
+            break;
+        default:
+            break;
+    }
+}
+
+- (void)playbackDidStop:(NSNotification *)notification
+{
+    [self dismissPlaybackView];
+}
+
+- (void)playbackDidFail:(NSNotification *)notification
+{
+    [self showPlaybackError];
+}
+
+#pragma mark - API
+
+- (void)showFullscreenPlayback
+{
+    self.displayMode = VLCPlayerDisplayControllerDisplayModeFullscreen;
+    [self _presentFullscreenPlaybackViewIfNeeded];
+}
+
+- (void)closeFullscreenPlayback
+{
+    [self _closeFullscreenPlayback];
+    self.displayMode = VLCPlayerDisplayControllerDisplayModeMiniplayer;
+    [self _showHideMiniPlaybackView];
+}
+
+#pragma mark - presentation handling
+- (BOOL)shouldAnimate
+{
+    return [[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground;
+}
+
+
+- (void)dismissPlaybackView
+{
+    switch (self.displayMode) {
+        case VLCPlayerDisplayControllerDisplayModeFullscreen:
+            [self _closeFullscreenPlayback];
+            break;
+        case VLCPlayerDisplayControllerDisplayModeMiniplayer:
+            [self _showHideMiniPlaybackView];
+        default:
+            break;
+    }
+}
+
+- (void)showPlaybackError
+{
+    NSString *failedString = NSLocalizedString(@"PLAYBACK_FAILED", nil);
+    switch (self.displayMode) {
+        case VLCPlayerDisplayControllerDisplayModeFullscreen:
+            [self.movieViewController showStatusMessage:failedString];
+            break;
+        case VLCPlayerDisplayControllerDisplayModeMiniplayer:
+        default:
+            [[[UIAlertView alloc] initWithTitle:failedString
+                                        message:nil
+                                       delegate:nil
+                              cancelButtonTitle:NSLocalizedString(@"BUTTON_OK", nil)
+                              otherButtonTitles:nil] show];
+            break;
+    }
+}
+
+
+
+#pragma mark - fullscreen player
+- (void)_presentFullscreenPlaybackViewIfNeeded
+{
+    if (!self.movieViewController.presentingViewController) {
+        [self _presentMovieViewControllerAnimated:[self shouldAnimate]];
+    }
+}
+
+- (void)_closeFullscreenPlayback
+{
+    BOOL animated = [self shouldAnimate];
+    [self.movieViewController setControlsHidden:YES animated:animated];
+    [self.movieViewController dismissViewControllerAnimated:animated completion:nil];
+    [self _showHideMiniPlaybackView];
+}
+
+- (void)_presentMovieViewControllerAnimated:(BOOL)animated
+{
+    VLCMovieViewController *movieViewController = self.movieViewController;
+    UINavigationController *navCon = [[VLCPlaybackNavigationController alloc] initWithRootViewController:movieViewController];
+    [movieViewController prepareForMediaPlayback:self.playbackController];
+    navCon.modalPresentationStyle = UIModalPresentationFullScreen;
+    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
+    [window.rootViewController presentViewController:navCon animated:animated completion:nil];
+
+}
+
+#pragma mark - miniplayer
+
+
+- (void)_showHideMiniPlaybackView
+{
+
+    VLCPlaybackController *playbackController = [VLCPlaybackController sharedInstance];
+    VLCMiniPlaybackView *miniPlaybackView = self.miniPlaybackView;
+    const NSTimeInterval animationDuration = 0.25;
+    const BOOL activePlaybackSession = playbackController.activePlaybackSession;
+    const BOOL miniPlayerVisible = miniPlaybackView.visible;
+
+    const CGRect viewRect = self.view.frame;
+    const CGFloat miniPlayerHeight = 60.;
+    const CGRect miniPlayerFrameIn =  CGRectMake(0., viewRect.size.height-miniPlayerHeight, viewRect.size.width, miniPlayerHeight);
+    const CGRect miniPlayerFrameOut = CGRectMake(0., viewRect.size.height, viewRect.size.width, miniPlayerHeight);
+
+    BOOL needsShow = activePlaybackSession && !miniPlayerVisible;
+    BOOL needsHide = !activePlaybackSession && miniPlayerVisible;
+
+    if (self.editing) {
+        needsHide = YES;
+        needsShow = NO;
+    }
+
+    void (^completionBlock)(BOOL) = nil;
+    if (needsShow) {
+        if (!miniPlaybackView) {
+            self.miniPlaybackView = miniPlaybackView = [[VLCMiniPlaybackView alloc] initWithFrame:miniPlayerFrameOut];
+            miniPlaybackView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
+            [self.view addSubview:miniPlaybackView];
+        }
+        miniPlaybackView.visible = YES;
+    } else if (needsHide) {
+        miniPlaybackView.visible = NO;
+        completionBlock = ^(BOOL finished) {
+            VLCMiniPlaybackView *miniPlaybackView = self.miniPlaybackView;
+            if (miniPlaybackView.visible == NO) {
+                [miniPlaybackView removeFromSuperview];
+                miniPlaybackView = nil;
+            }
+        };
+    }
+    //when switching between tableview and collectionview all subviews are removed, make sure to readd it when this happens
+    if (!miniPlaybackView.superview && miniPlayerVisible) {
+        [self.view addSubview:miniPlaybackView];
+    }
+    // either way update view
+    [miniPlaybackView setupForWork:playbackController];
+
+    if (needsShow || needsHide) {
+        UIViewController *childViewController = self.childViewController;
+
+        const CGRect newMiniPlayerFrame = needsHide ? miniPlayerFrameOut : miniPlayerFrameIn;
+        CGRect newChildViewFrame = childViewController.view.frame;
+        newChildViewFrame.size.height = CGRectGetMinY(newMiniPlayerFrame)-CGRectGetMinY(newChildViewFrame);
+
+        [UIView animateWithDuration:animationDuration
+                              delay:animationDuration
+                            options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction
+                         animations:^{
+                             miniPlaybackView.frame = newMiniPlayerFrame;
+                             childViewController.view.frame = newChildViewFrame;
+                         }
+                         completion:completionBlock];
+    }
+    
+}
+
+@end

+ 0 - 1
Sources/VLCPlaylistViewController.h

@@ -25,7 +25,6 @@
 
 - (void)updateViewContents;
 - (void)removeMediaObject:(id)mediaObject updateDatabase:(BOOL)updateDB;
-- (void)displayMiniPlaybackViewIfNeeded;
 
 - (void)setLibraryMode:(VLCLibraryMode)mode;
 

+ 0 - 79
Sources/VLCPlaylistViewController.m

@@ -27,8 +27,6 @@
 #import "VLCAlertView.h"
 #import "VLCOpenInActivity.h"
 #import "VLCNavigationController.h"
-#import "VLCPlaybackController.h"
-#import "VLCMiniPlaybackView.h"
 
 #import <AssetsLibrary/AssetsLibrary.h>
 
@@ -67,7 +65,6 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
 
     UIBarButtonItem *_actionBarButtonItem;
     VLCOpenInActivity *_openInActivity;
-    VLCMiniPlaybackView *_miniPlaybackView;
 }
 
 @property (nonatomic, strong) UITableView *tableView;
@@ -148,10 +145,7 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
         UIScrollView *playlistView = _usingTableViewToShowData ? _tableView : _collectionView;
         playlistView.contentInset = UIEdgeInsetsMake(originY, 0, 0, 0);
     }
-
-    [self adjustScrollViewInsetsForMiniPlayerVisible:_miniPlaybackView.visible];
     self.view = contentView;
-    [self displayMiniPlaybackViewIfNeeded];
 }
 
 #pragma mark -
@@ -236,7 +230,6 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
     [super viewWillAppear:animated];
     [self.collectionView.collectionViewLayout invalidateLayout];
     [self _displayEmptyLibraryViewIfNeeded];
-    [self displayMiniPlaybackViewIfNeeded];
 }
 
 - (void)viewDidAppear:(BOOL)animated
@@ -437,75 +430,6 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
         [self.collectionView.collectionViewLayout invalidateLayout];
 }
 
-- (void)displayMiniPlaybackViewIfNeeded
-{
-    VLCPlaybackController *playbackController = [VLCPlaybackController sharedInstance];
-
-    const NSTimeInterval animationDuration = 0.25;
-    const BOOL showMiniPlayer = playbackController.activePlaybackSession;
-    const BOOL miniPlayerVisible = _miniPlaybackView.visible;
-
-    const CGRect viewRect = self.view.frame;
-    const CGFloat miniPlayerHeight = 60.;
-    const CGRect miniPlayerFrameIn =  CGRectMake(0., viewRect.size.height-miniPlayerHeight, viewRect.size.width, miniPlayerHeight);
-    const CGRect miniPlayerFrameOut = CGRectMake(0., viewRect.size.height, viewRect.size.width, miniPlayerHeight);
-
-    BOOL needsShow = showMiniPlayer && !miniPlayerVisible;
-    BOOL needsHide = !showMiniPlayer && miniPlayerVisible;
-
-    if (self.editing) {
-        needsHide = YES;
-        needsShow = NO;
-    }
-
-    void (^completionBlock)(BOOL) = nil;
-    if (needsShow) {
-        if (!_miniPlaybackView) {
-            _miniPlaybackView = [[VLCMiniPlaybackView alloc] initWithFrame:miniPlayerFrameOut];
-            _miniPlaybackView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
-            [self.view addSubview:_miniPlaybackView];
-        }
-        _miniPlaybackView.visible = YES;
-    } else if (needsHide) {
-        _miniPlaybackView.visible = NO;
-        completionBlock = ^(BOOL finished) {
-            if (_miniPlaybackView.visible == NO) {
-                [_miniPlaybackView removeFromSuperview];
-                _miniPlaybackView = nil;
-            }
-        };
-    }
-    //when switching between tableview and collectionview all subviews are removed, make sure to readd it when this happens
-    if (!_miniPlaybackView.superview && miniPlayerVisible) {
-        [self.view addSubview:_miniPlaybackView];
-    }
-    // either way update view
-    [_miniPlaybackView setupForWork];
-
-    if (needsShow || needsHide) {
-        const CGRect newFrame = needsHide ? miniPlayerFrameOut : miniPlayerFrameIn;
-
-        [UIView animateWithDuration:animationDuration
-                              delay:animationDuration
-                            options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction
-                         animations:^{
-                             _miniPlaybackView.frame = newFrame;
-                             [self adjustScrollViewInsetsForMiniPlayerVisible:needsShow];
-                         }
-                         completion:completionBlock];
-    }
-
-}
-- (void)adjustScrollViewInsetsForMiniPlayerVisible:(BOOL)miniPlayerVisible
-{
-    const CGFloat bottomInset = miniPlayerVisible ? CGRectGetHeight(_miniPlaybackView.frame) : 0.;
-    UIScrollView *playListDataView = _usingTableViewToShowData ? _tableView : _collectionView;
-    UIEdgeInsets inset = playListDataView.contentInset;
-    inset.bottom = bottomInset;
-    playListDataView.contentInset = inset;
-    playListDataView.scrollIndicatorInsets = inset;
-}
-
 - (void)libraryUpgradeComplete
 {
     self.title = NSLocalizedString(@"LIBRARY_ALL_FILES", nil);
@@ -613,7 +537,6 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
     }
 
     [self _displayEmptyLibraryViewIfNeeded];
-    [self displayMiniPlaybackViewIfNeeded];
 }
 
 #pragma mark - Table View
@@ -1105,8 +1028,6 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
 {
     [super setEditing:editing animated:animated];
 
-    [self displayMiniPlaybackViewIfNeeded];
-
     UIBarButtonItem *editButton = self.editButtonItem;
     NSString *editImage = editing? @"doneButton": @"button";
     NSString *editImageHighlight = editing? @"doneButtonHighlight": @"buttonHighlight";

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

@@ -236,6 +236,7 @@
 		DD1542121ACFF76400AFD4EC /* VLCWatchTableController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1542111ACFF76400AFD4EC /* VLCWatchTableController.m */; };
 		DD3EA6311AF50CFE007FF096 /* VLCWatchMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3EA6301AF50CFE007FF096 /* VLCWatchMessage.m */; };
 		DD3EA6321AF50D01007FF096 /* VLCWatchMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3EA6301AF50CFE007FF096 /* VLCWatchMessage.m */; };
+		DD510B701B14E564003BA71C /* VLCPlayerDisplayController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD510B6F1B14E564003BA71C /* VLCPlayerDisplayController.m */; };
 		DD670C971AFBEED400A2D7AB /* MappingModel_2_5_to_2_6.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = DDB959411AFBB30500BB8CFF /* MappingModel_2_5_to_2_6.xcmappingmodel */; };
 		DD6FA7B01ACD641C006DEB2E /* VLCNowPlayingInterfaceController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD6FA7AF1ACD641C006DEB2E /* VLCNowPlayingInterfaceController.m */; };
 		DD7110F01AF38B2B00854776 /* MLMediaLibrary+playlist.m in Sources */ = {isa = PBXBuildFile; fileRef = DD7110EF1AF38B2B00854776 /* MLMediaLibrary+playlist.m */; };
@@ -879,6 +880,8 @@
 		DD1542111ACFF76400AFD4EC /* VLCWatchTableController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCWatchTableController.m; sourceTree = "<group>"; };
 		DD3EA62F1AF50CFE007FF096 /* VLCWatchMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCWatchMessage.h; sourceTree = "<group>"; };
 		DD3EA6301AF50CFE007FF096 /* VLCWatchMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCWatchMessage.m; sourceTree = "<group>"; };
+		DD510B6E1B14E564003BA71C /* VLCPlayerDisplayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCPlayerDisplayController.h; path = Sources/VLCPlayerDisplayController.h; sourceTree = SOURCE_ROOT; };
+		DD510B6F1B14E564003BA71C /* VLCPlayerDisplayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCPlayerDisplayController.m; path = Sources/VLCPlayerDisplayController.m; sourceTree = SOURCE_ROOT; };
 		DD6FA7AE1ACD641C006DEB2E /* VLCNowPlayingInterfaceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCNowPlayingInterfaceController.h; sourceTree = "<group>"; };
 		DD6FA7AF1ACD641C006DEB2E /* VLCNowPlayingInterfaceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCNowPlayingInterfaceController.m; sourceTree = "<group>"; };
 		DD7110EE1AF38B2B00854776 /* MLMediaLibrary+playlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MLMediaLibrary+playlist.h"; sourceTree = "<group>"; };
@@ -1346,6 +1349,8 @@
 			children = (
 				7DE56C181AD93F9100E8CA00 /* VLCPlaybackController.h */,
 				7DE56C191AD93F9100E8CA00 /* VLCPlaybackController.m */,
+				DD510B6E1B14E564003BA71C /* VLCPlayerDisplayController.h */,
+				DD510B6F1B14E564003BA71C /* VLCPlayerDisplayController.m */,
 				DD8F842F1B00EB3B0009138A /* VLCPlaybackController+MediaLibrary.h */,
 				DD8F84301B00EB3B0009138A /* VLCPlaybackController+MediaLibrary.m */,
 				7D37848D183A98B6009EE944 /* VLCMovieViewController.h */,
@@ -2183,6 +2188,7 @@
 				7D74177A1AE2D3CE001F1997 /* VLCNavigationController.m in Sources */,
 				7D30F3E2183AB33200FFC021 /* VLCSidebarViewCell.m in Sources */,
 				7D30F3EA183AB34200FFC021 /* VLCGoogleDriveController.m in Sources */,
+				DD510B701B14E564003BA71C /* VLCPlayerDisplayController.m in Sources */,
 				9B088308183D7BEC004B5C2A /* VLCCloudStorageTableViewController.m in Sources */,
 				DDE4906D1ACDBEA000B1B5E3 /* VLCNotificationRelay.m in Sources */,
 				7D30F3EC183AB34200FFC021 /* VLCGoogleDriveTableViewController.m in Sources */,