VLCFullscreenMovieTVViewController.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*****************************************************************************
  2. * VLC for iOS
  3. *****************************************************************************
  4. * Copyright (c) 2015 VideoLAN. All rights reserved.
  5. * $Id$
  6. *
  7. * Authors: Felix Paul Kühne <fkuehne # videolan.org>
  8. *
  9. * Refer to the COPYING file of the official project for license.
  10. *****************************************************************************/
  11. #import "VLCFullscreenMovieTVViewController.h"
  12. #import "VLCPlaybackInfoTVViewController.h"
  13. @interface VLCFullscreenMovieTVViewController (UIViewControllerTransitioningDelegate) <UIViewControllerTransitioningDelegate, UIGestureRecognizerDelegate>
  14. @end
  15. @interface VLCFullscreenMovieTVViewController ()
  16. {
  17. BOOL _playerIsSetup;
  18. BOOL _viewAppeared;
  19. }
  20. @end
  21. @implementation VLCFullscreenMovieTVViewController
  22. + (instancetype)fullscreenMovieTVViewController
  23. {
  24. return [[self alloc] initWithNibName:nil bundle:nil];
  25. }
  26. - (void)viewDidLoad {
  27. [super viewDidLoad];
  28. self.extendedLayoutIncludesOpaqueBars = YES;
  29. self.edgesForExtendedLayout = UIRectEdgeAll;
  30. NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
  31. [center addObserver:self
  32. selector:@selector(playbackDidStop:)
  33. name:VLCPlaybackControllerPlaybackDidStop
  34. object:nil];
  35. _movieView.userInteractionEnabled = NO;
  36. _playerIsSetup = NO;
  37. self.titleLabel.text = @"";
  38. self.transportBar.bufferStartFraction = 0.0;
  39. self.transportBar.bufferEndFraction = 1.0;
  40. self.transportBar.playbackFraction = 0.0;
  41. self.transportBar.scrubbingFraction = 0.0;
  42. self.dimmingView.alpha = 0.0;
  43. self.bottomOverlayView.hidden = YES;
  44. self.bufferingLabel.text = NSLocalizedString(@"PLEASE_WAIT", nil);
  45. // Panning and Swiping
  46. UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)];
  47. [self.view addGestureRecognizer:panGestureRecognizer];
  48. // Button presses
  49. UITapGestureRecognizer *playpauseGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(playPausePressed)];
  50. playpauseGesture.allowedPressTypes = @[@(UIPressTypePlayPause)];
  51. [self.view addGestureRecognizer:playpauseGesture];
  52. UITapGestureRecognizer *selectTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(selectButtonPressed:)];
  53. selectTapGestureRecognizer.allowedPressTypes = @[@(UIPressTypeSelect)];
  54. [self.view addGestureRecognizer:selectTapGestureRecognizer];
  55. UITapGestureRecognizer *menuTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(menuButtonPressed:)];
  56. menuTapGestureRecognizer.allowedPressTypes = @[@(UIPressTypeMenu)];
  57. menuTapGestureRecognizer.delegate = self;
  58. [self.view addGestureRecognizer:menuTapGestureRecognizer];
  59. UITapGestureRecognizer *upArrowRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showInfoVCIfNotScrubbing)];
  60. upArrowRecognizer.allowedPressTypes = @[@(UIPressTypeUpArrow)];
  61. [self.view addGestureRecognizer:upArrowRecognizer];
  62. }
  63. #pragma mark - view events
  64. - (void)viewWillAppear:(BOOL)animated
  65. {
  66. [super viewWillAppear:animated];
  67. [self.navigationController setNavigationBarHidden:YES animated:animated];
  68. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  69. vpc.delegate = self;
  70. [vpc recoverPlaybackState];
  71. }
  72. - (void)viewDidAppear:(BOOL)animated
  73. {
  74. [super viewDidAppear:animated];
  75. _viewAppeared = YES;
  76. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  77. [vpc recoverDisplayedMetadata];
  78. vpc.videoOutputView = nil;
  79. vpc.videoOutputView = self.movieView;
  80. [[NSNotificationCenter defaultCenter] removeObserver:self];
  81. }
  82. - (void)viewWillDisappear:(BOOL)animated
  83. {
  84. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  85. if (vpc.videoOutputView == self.movieView) {
  86. vpc.videoOutputView = nil;
  87. }
  88. _viewAppeared = NO;
  89. [self.navigationController setNavigationBarHidden:NO animated:YES];
  90. [vpc stopPlayback];
  91. [super viewWillDisappear:animated];
  92. }
  93. - (BOOL)canBecomeFirstResponder
  94. {
  95. return YES;
  96. }
  97. #pragma mark - UIActions
  98. - (void)playPausePressed
  99. {
  100. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  101. [vpc playPause];
  102. }
  103. - (void)panGesture:(UIPanGestureRecognizer *)panGestureRecognizer
  104. {
  105. VLCTransportBar *bar = self.transportBar;
  106. UIView *view = self.view;
  107. CGPoint translation = [panGestureRecognizer translationInView:view];
  108. if (!bar.scrubbing) {
  109. if (ABS(translation.x) > 150.0) {
  110. [self startScrubbing];
  111. } else if (translation.y > 200.0) {
  112. [self showInfoVCIfNotScrubbing];
  113. return;
  114. } else {
  115. return;
  116. }
  117. }
  118. const CGFloat scaleFactor = 8.0;
  119. CGFloat fractionInView = translation.x/CGRectGetWidth(view.bounds)/scaleFactor;
  120. translation.x = 0.0;
  121. [panGestureRecognizer setTranslation:translation inView:view];
  122. CGFloat scrubbingFraction = MAX(0.0, MIN(bar.scrubbingFraction + fractionInView,1.0));
  123. bar.scrubbingFraction = scrubbingFraction;
  124. [self updateTimeLabelsForScrubbingFraction:scrubbingFraction];
  125. }
  126. - (void)selectButtonPressed:(UITapGestureRecognizer *)recognizer
  127. {
  128. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  129. VLCTransportBar *bar = self.transportBar;
  130. if (bar.scrubbing) {
  131. bar.playbackFraction = bar.scrubbingFraction;
  132. [vpc.mediaPlayer setPosition:bar.scrubbingFraction];
  133. [self stopScrubbing];
  134. }
  135. }
  136. - (void)menuButtonPressed:(UITapGestureRecognizer *)recognizer
  137. {
  138. VLCTransportBar *bar = self.transportBar;
  139. if (bar.scrubbing) {
  140. [UIView animateWithDuration:0.3 animations:^{
  141. bar.scrubbingFraction = bar.playbackFraction;
  142. [bar layoutIfNeeded];
  143. }];
  144. [self updateTimeLabelsForScrubbingFraction:bar.playbackFraction];
  145. [self stopScrubbing];
  146. }
  147. }
  148. - (void)showInfoVCIfNotScrubbing
  149. {
  150. if (self.transportBar.scrubbing) {
  151. return;
  152. }
  153. VLCPlaybackInfoTVViewController *infoController = [[VLCPlaybackInfoTVViewController alloc] initWithNibName:nil bundle:nil];
  154. infoController.transitioningDelegate = self;
  155. infoController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
  156. // TODO: configure with player info
  157. [self presentViewController:infoController animated:YES completion:nil];
  158. }
  159. #pragma mark -
  160. - (void)updateTimeLabelsForScrubbingFraction:(CGFloat)scrubbingFraction
  161. {
  162. VLCTransportBar *bar = self.transportBar;
  163. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  164. // MAX 1, _ is ugly hack to prevent --:-- instead of 00:00
  165. int scrubbingTimeInt = MAX(1,vpc.mediaDuration*scrubbingFraction);
  166. VLCTime *scrubbingTime = [VLCTime timeWithInt:scrubbingTimeInt];
  167. bar.markerTimeLabel.text = [scrubbingTime stringValue];
  168. VLCTime *remainingTime = [VLCTime timeWithInt:(int)vpc.mediaDuration-scrubbingTime.intValue];
  169. bar.remainingTimeLabel.text = [remainingTime stringValue];
  170. }
  171. - (void)startScrubbing
  172. {
  173. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  174. self.transportBar.scrubbing = YES;
  175. [self updateDimmingView];
  176. if (vpc.isPlaying) {
  177. [vpc playPause];
  178. }
  179. }
  180. - (void)stopScrubbing
  181. {
  182. self.transportBar.scrubbing = NO;
  183. [self updateDimmingView];
  184. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  185. [vpc.mediaPlayer play];
  186. }
  187. - (void)updateDimmingView
  188. {
  189. BOOL shouldBeVisible = self.transportBar.scrubbing;
  190. BOOL isVisible = self.dimmingView.alpha == 1.0;
  191. if (shouldBeVisible != isVisible) {
  192. [UIView animateWithDuration:0.3 animations:^{
  193. self.dimmingView.alpha = shouldBeVisible ? 1.0 : 0.0;
  194. }];
  195. }
  196. }
  197. - (void)updateActivityIndicatorForState:(VLCMediaPlayerState)state {
  198. UIActivityIndicatorView *indicator = self.activityIndicator;
  199. switch (state) {
  200. case VLCMediaPlayerStateBuffering:
  201. if (!indicator.isAnimating) {
  202. self.activityIndicator.alpha = 1.0;
  203. [self.activityIndicator startAnimating];
  204. }
  205. break;
  206. default:
  207. if (indicator.isAnimating) {
  208. [self.activityIndicator stopAnimating];
  209. self.activityIndicator.alpha = 0.0;
  210. }
  211. break;
  212. }
  213. }
  214. #pragma mark - playback controller delegation
  215. - (void)prepareForMediaPlayback:(VLCPlaybackController *)controller
  216. {
  217. APLog(@"%s", __PRETTY_FUNCTION__);
  218. }
  219. - (void)playbackDidStop:(NSNotification *)aNotification
  220. {
  221. [self dismissViewControllerAnimated:YES completion:nil];
  222. }
  223. - (void)mediaPlayerStateChanged:(VLCMediaPlayerState)currentState
  224. isPlaying:(BOOL)isPlaying
  225. currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
  226. currentMediaHasChapters:(BOOL)currentMediaHasChapters
  227. forPlaybackController:(VLCPlaybackController *)controller
  228. {
  229. [self updateActivityIndicatorForState:currentState];
  230. if (controller.isPlaying && !self.bufferingLabel.hidden) {
  231. [UIView animateWithDuration:.3 animations:^{
  232. self.bufferingLabel.hidden = YES;
  233. self.bottomOverlayView.hidden = NO;
  234. }];
  235. }
  236. }
  237. - (void)displayMetadataForPlaybackController:(VLCPlaybackController *)controller
  238. title:(NSString *)title
  239. artwork:(UIImage *)artwork
  240. artist:(NSString *)artist
  241. album:(NSString *)album
  242. audioOnly:(BOOL)audioOnly
  243. {
  244. self.titleLabel.text = title;
  245. }
  246. - (void)playbackPositionUpdated:(VLCPlaybackController *)controller
  247. {
  248. VLCMediaPlayer *mediaPlayer = [VLCPlaybackController sharedInstance].mediaPlayer;
  249. // FIXME: hard coded state since the state in mediaPlayer is incorrectly still buffering
  250. [self updateActivityIndicatorForState:VLCMediaPlayerStatePlaying];
  251. VLCTransportBar *transportBar = self.transportBar;
  252. transportBar.remainingTimeLabel.text = [[mediaPlayer remainingTime] stringValue];
  253. transportBar.markerTimeLabel.text = [[mediaPlayer time] stringValue];
  254. transportBar.playbackFraction = mediaPlayer.position;
  255. }
  256. #pragma mark - gesture recognizer delegate
  257. - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
  258. if ([gestureRecognizer.allowedPressTypes containsObject:@(UIPressTypeMenu)]) {
  259. return self.transportBar.scrubbing;
  260. }
  261. return YES;
  262. }
  263. @end
  264. @implementation VLCFullscreenMovieTVViewController (UIViewControllerTransitioningDelegate)
  265. - (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
  266. {
  267. return [[VLCPlaybackInfoTVTransitioningAnimator alloc] init];
  268. }
  269. - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
  270. {
  271. return [[VLCPlaybackInfoTVTransitioningAnimator alloc] init];
  272. }
  273. @end