VLCFullscreenMovieTVViewController.m 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  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. #import "VLCPlaybackInfoTVAnimators.h"
  14. #import "VLCIRTVTapGestureRecognizer.h"
  15. #import "VLCHTTPUploaderController.h"
  16. #import "VLCSiriRemoteGestureRecognizer.h"
  17. typedef NS_ENUM(NSInteger, VLCPlayerScanState)
  18. {
  19. VLCPlayerScanStateNone,
  20. VLCPlayerScanStateForward2,
  21. VLCPlayerScanStateForward4,
  22. };
  23. @interface VLCFullscreenMovieTVViewController (UIViewControllerTransitioningDelegate) <UIViewControllerTransitioningDelegate, UIGestureRecognizerDelegate>
  24. @end
  25. @interface VLCFullscreenMovieTVViewController ()
  26. @property (nonatomic) NSTimer *hidePlaybackControlsViewAfterDeleayTimer;
  27. @property (nonatomic) VLCPlaybackInfoTVViewController *infoViewController;
  28. @property (nonatomic) NSNumber *scanSavedPlaybackRate;
  29. @property (nonatomic) VLCPlayerScanState scanState;
  30. @end
  31. @implementation VLCFullscreenMovieTVViewController
  32. + (instancetype)fullscreenMovieTVViewController
  33. {
  34. return [[self alloc] initWithNibName:nil bundle:nil];
  35. }
  36. - (void)viewDidLoad
  37. {
  38. [super viewDidLoad];
  39. self.extendedLayoutIncludesOpaqueBars = YES;
  40. self.edgesForExtendedLayout = UIRectEdgeAll;
  41. NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
  42. [center addObserver:self
  43. selector:@selector(playbackDidStop:)
  44. name:VLCPlaybackControllerPlaybackDidStop
  45. object:nil];
  46. _movieView.userInteractionEnabled = NO;
  47. self.titleLabel.text = @"";
  48. self.transportBar.bufferStartFraction = 0.0;
  49. self.transportBar.bufferEndFraction = 1.0;
  50. self.transportBar.playbackFraction = 0.0;
  51. self.transportBar.scrubbingFraction = 0.0;
  52. self.dimmingView.alpha = 0.0;
  53. self.bottomOverlayView.alpha = 0.0;
  54. self.bufferingLabel.text = NSLocalizedString(@"PLEASE_WAIT", nil);
  55. // Panning and Swiping
  56. UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)];
  57. panGestureRecognizer.delegate = self;
  58. [self.view addGestureRecognizer:panGestureRecognizer];
  59. // Button presses
  60. UITapGestureRecognizer *playpauseGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(playPausePressed)];
  61. playpauseGesture.allowedPressTypes = @[@(UIPressTypePlayPause)];
  62. [self.view addGestureRecognizer:playpauseGesture];
  63. UITapGestureRecognizer *menuTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(menuButtonPressed:)];
  64. menuTapGestureRecognizer.allowedPressTypes = @[@(UIPressTypeMenu)];
  65. menuTapGestureRecognizer.delegate = self;
  66. [self.view addGestureRecognizer:menuTapGestureRecognizer];
  67. // IR only recognizer
  68. UITapGestureRecognizer *downArrowRecognizer = [[VLCIRTVTapGestureRecognizer alloc] initWithTarget:self action:@selector(showInfoVCIfNotScrubbing)];
  69. downArrowRecognizer.allowedPressTypes = @[@(UIPressTypeDownArrow)];
  70. [self.view addGestureRecognizer:downArrowRecognizer];
  71. UITapGestureRecognizer *leftArrowRecognizer = [[VLCIRTVTapGestureRecognizer alloc] initWithTarget:self action:@selector(handleIRPressLeft)];
  72. leftArrowRecognizer.allowedPressTypes = @[@(UIPressTypeLeftArrow)];
  73. [self.view addGestureRecognizer:leftArrowRecognizer];
  74. UITapGestureRecognizer *rightArrowRecognizer = [[VLCIRTVTapGestureRecognizer alloc] initWithTarget:self action:@selector(handleIRPressRight)];
  75. rightArrowRecognizer.allowedPressTypes = @[@(UIPressTypeRightArrow)];
  76. [self.view addGestureRecognizer:rightArrowRecognizer];
  77. // Siri remote arrow presses
  78. VLCSiriRemoteGestureRecognizer *siriArrowRecognizer = [[VLCSiriRemoteGestureRecognizer alloc] initWithTarget:self action:@selector(handleSiriRemote:)];
  79. siriArrowRecognizer.delegate = self;
  80. [self.view addGestureRecognizer:siriArrowRecognizer];
  81. }
  82. - (void)didReceiveMemoryWarning
  83. {
  84. [super didReceiveMemoryWarning];
  85. self.infoViewController = nil;
  86. }
  87. #pragma mark - view events
  88. - (void)viewWillAppear:(BOOL)animated
  89. {
  90. [super viewWillAppear:animated];
  91. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  92. vpc.delegate = self;
  93. [vpc recoverPlaybackState];
  94. }
  95. - (void)viewDidAppear:(BOOL)animated
  96. {
  97. [super viewDidAppear:animated];
  98. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  99. [vpc recoverDisplayedMetadata];
  100. vpc.videoOutputView = nil;
  101. vpc.videoOutputView = self.movieView;
  102. [[NSNotificationCenter defaultCenter] removeObserver:self];
  103. }
  104. - (void)viewWillDisappear:(BOOL)animated
  105. {
  106. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  107. if (vpc.videoOutputView == self.movieView) {
  108. vpc.videoOutputView = nil;
  109. }
  110. [vpc stopPlayback];
  111. [super viewWillDisappear:animated];
  112. /* clean caches in case remote playback was used
  113. * note that if we cancel before the upload is complete
  114. * the cache won't be emptied, but on the next launch only (or if the system is under storage pressure)
  115. */
  116. [[VLCHTTPUploaderController sharedInstance] cleanCache];
  117. }
  118. - (BOOL)canBecomeFirstResponder
  119. {
  120. return YES;
  121. }
  122. #pragma mark - UIActions
  123. - (void)playPausePressed
  124. {
  125. [self showPlaybackControlsIfNeededForUserInteraction];
  126. [self setScanState:VLCPlayerScanStateNone];
  127. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  128. if (self.transportBar.scrubbing) {
  129. [self selectButtonPressed];
  130. } else {
  131. [vpc playPause];
  132. }
  133. }
  134. - (void)panGesture:(UIPanGestureRecognizer *)panGestureRecognizer
  135. {
  136. switch (panGestureRecognizer.state) {
  137. case UIGestureRecognizerStateCancelled:
  138. case UIGestureRecognizerStateFailed:
  139. return;
  140. default:
  141. break;
  142. }
  143. VLCTransportBar *bar = self.transportBar;
  144. UIView *view = self.view;
  145. CGPoint translation = [panGestureRecognizer translationInView:view];
  146. if (!bar.scrubbing) {
  147. if (ABS(translation.x) > 150.0) {
  148. [self startScrubbing];
  149. } else if (translation.y > 200.0) {
  150. panGestureRecognizer.enabled = NO;
  151. panGestureRecognizer.enabled = YES;
  152. [self showInfoVCIfNotScrubbing];
  153. return;
  154. } else {
  155. return;
  156. }
  157. }
  158. [self showPlaybackControlsIfNeededForUserInteraction];
  159. [self setScanState:VLCPlayerScanStateNone];
  160. const CGFloat scaleFactor = 8.0;
  161. CGFloat fractionInView = translation.x/CGRectGetWidth(view.bounds)/scaleFactor;
  162. CGFloat scrubbingFraction = MAX(0.0, MIN(bar.scrubbingFraction + fractionInView,1.0));
  163. if (ABS(scrubbingFraction - bar.playbackFraction)<0.005) {
  164. scrubbingFraction = bar.playbackFraction;
  165. } else {
  166. translation.x = 0.0;
  167. [panGestureRecognizer setTranslation:translation inView:view];
  168. }
  169. [UIView animateWithDuration:0.3
  170. delay:0.0
  171. options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState
  172. animations:^{
  173. bar.scrubbingFraction = scrubbingFraction;
  174. }
  175. completion:nil];
  176. [self updateTimeLabelsForScrubbingFraction:scrubbingFraction];
  177. }
  178. - (void)selectButtonPressed
  179. {
  180. [self showPlaybackControlsIfNeededForUserInteraction];
  181. [self setScanState:VLCPlayerScanStateNone];
  182. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  183. VLCTransportBar *bar = self.transportBar;
  184. if (bar.scrubbing) {
  185. bar.playbackFraction = bar.scrubbingFraction;
  186. [vpc.mediaPlayer setPosition:bar.scrubbingFraction];
  187. [self stopScrubbing];
  188. } else if(vpc.mediaPlayer.playing) {
  189. [vpc.mediaPlayer pause];
  190. }
  191. }
  192. - (void)menuButtonPressed:(UITapGestureRecognizer *)recognizer
  193. {
  194. VLCTransportBar *bar = self.transportBar;
  195. if (bar.scrubbing) {
  196. [UIView animateWithDuration:0.3 animations:^{
  197. bar.scrubbingFraction = bar.playbackFraction;
  198. [bar layoutIfNeeded];
  199. }];
  200. [self updateTimeLabelsForScrubbingFraction:bar.playbackFraction];
  201. [self stopScrubbing];
  202. [self hidePlaybackControlsIfNeededAfterDelay];
  203. }
  204. }
  205. - (void)showInfoVCIfNotScrubbing
  206. {
  207. if (self.transportBar.scrubbing) {
  208. return;
  209. }
  210. // TODO: configure with player info
  211. VLCPlaybackInfoTVViewController *infoViewController = self.infoViewController;
  212. infoViewController.transitioningDelegate = self;
  213. [self presentViewController:infoViewController animated:YES completion:nil];
  214. [self animatePlaybackControlsToVisibility:NO];
  215. }
  216. - (void)handleIRPressLeft
  217. {
  218. [self showPlaybackControlsIfNeededForUserInteraction];
  219. BOOL paused = ![VLCPlaybackController sharedInstance].isPlaying;
  220. if (paused) {
  221. [self jumpBackward];
  222. } else
  223. {
  224. [self scanForwardPrevious];
  225. }
  226. }
  227. - (void)handleIRPressRight
  228. {
  229. [self showPlaybackControlsIfNeededForUserInteraction];
  230. BOOL paused = ![VLCPlaybackController sharedInstance].isPlaying;
  231. if (paused) {
  232. [self jumpForward];
  233. } else {
  234. [self scanForwardNext];
  235. }
  236. }
  237. - (void)handleSiriRemote:(VLCSiriRemoteGestureRecognizer *)recognizer
  238. {
  239. [self showPlaybackControlsIfNeededForUserInteraction];
  240. VLCTransportBarHint hint = self.transportBar.hint;
  241. switch (recognizer.state) {
  242. case UIGestureRecognizerStateBegan:
  243. case UIGestureRecognizerStateChanged:
  244. if (recognizer.isLongPress) {
  245. if (recognizer.touchLocation == VLCSiriRemoteTouchLocationRight) {
  246. [self setScanState:VLCPlayerScanStateForward2];
  247. return;
  248. }
  249. } else {
  250. switch (recognizer.touchLocation) {
  251. case VLCSiriRemoteTouchLocationLeft:
  252. hint = VLCTransportBarHintJumpBackward10;
  253. break;
  254. case VLCSiriRemoteTouchLocationRight:
  255. hint = VLCTransportBarHintJumpForward10;
  256. break;
  257. default:
  258. hint = VLCTransportBarHintNone;
  259. break;
  260. }
  261. }
  262. break;
  263. case UIGestureRecognizerStateEnded:
  264. if (recognizer.isClick && !recognizer.isLongPress) {
  265. [self handleSiriPressUpAtLocation:recognizer.touchLocation];
  266. }
  267. [self setScanState:VLCPlayerScanStateNone];
  268. break;
  269. case UIGestureRecognizerStateCancelled:
  270. hint = VLCTransportBarHintNone;
  271. [self setScanState:VLCPlayerScanStateNone];
  272. break;
  273. default:
  274. break;
  275. }
  276. self.transportBar.hint = hint;
  277. }
  278. - (void)handleSiriPressUpAtLocation:(VLCSiriRemoteTouchLocation)location
  279. {
  280. switch (location) {
  281. case VLCSiriRemoteTouchLocationLeft:
  282. [self jumpBackward];
  283. break;
  284. case VLCSiriRemoteTouchLocationRight:
  285. [self jumpForward];
  286. break;
  287. default:
  288. [self selectButtonPressed];
  289. break;
  290. }
  291. }
  292. #pragma mark -
  293. static const NSInteger VLCJumpInterval = 10000; // 10 seconds
  294. - (void)jumpForward
  295. {
  296. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  297. VLCMediaPlayer *player = vpc.mediaPlayer;
  298. if (player.isPlaying) {
  299. [player jumpForward:VLCJumpInterval];
  300. } else {
  301. [self scrubbingJumpInterval:VLCJumpInterval];
  302. }
  303. }
  304. - (void)jumpBackward
  305. {
  306. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  307. VLCMediaPlayer *player = vpc.mediaPlayer;
  308. if (player.isPlaying) {
  309. [player jumpBackward:VLCJumpInterval];
  310. } else {
  311. [self scrubbingJumpInterval:-VLCJumpInterval];
  312. }
  313. }
  314. - (void)scrubbingJumpInterval:(NSInteger)interval
  315. {
  316. NSInteger duration = [VLCPlaybackController sharedInstance].mediaDuration;
  317. if (duration==0) {
  318. return;
  319. }
  320. CGFloat intervalFraction = ((CGFloat)interval)/((CGFloat)duration);
  321. VLCTransportBar *bar = self.transportBar;
  322. bar.scrubbing = YES;
  323. CGFloat currentFraction = bar.scrubbingFraction;
  324. currentFraction += intervalFraction;
  325. bar.scrubbingFraction = currentFraction;
  326. [self updateTimeLabelsForScrubbingFraction:currentFraction];
  327. }
  328. - (void)scanForwardNext
  329. {
  330. VLCPlayerScanState nextState = self.scanState;
  331. switch (self.scanState) {
  332. case VLCPlayerScanStateNone:
  333. nextState = VLCPlayerScanStateForward2;
  334. break;
  335. case VLCPlayerScanStateForward2:
  336. nextState = VLCPlayerScanStateForward4;
  337. break;
  338. case VLCPlayerScanStateForward4:
  339. return;
  340. default:
  341. return;
  342. }
  343. [self setScanState:nextState];
  344. }
  345. - (void)scanForwardPrevious
  346. {
  347. VLCPlayerScanState nextState = self.scanState;
  348. switch (self.scanState) {
  349. case VLCPlayerScanStateNone:
  350. return;
  351. case VLCPlayerScanStateForward2:
  352. nextState = VLCPlayerScanStateNone;
  353. break;
  354. case VLCPlayerScanStateForward4:
  355. nextState = VLCPlayerScanStateForward2;
  356. break;
  357. default:
  358. return;
  359. }
  360. [self setScanState:nextState];
  361. }
  362. - (void)setScanState:(VLCPlayerScanState)scanState
  363. {
  364. if (_scanState == scanState) {
  365. return;
  366. }
  367. if (_scanState == VLCPlayerScanStateNone) {
  368. self.scanSavedPlaybackRate = @([VLCPlaybackController sharedInstance].playbackRate);
  369. }
  370. _scanState = scanState;
  371. float rate = 1.0;
  372. VLCTransportBarHint hint = VLCTransportBarHintNone;
  373. switch (scanState) {
  374. case VLCPlayerScanStateForward2:
  375. rate = 2.0;
  376. hint = VLCTransportBarHintScanForward;
  377. break;
  378. case VLCPlayerScanStateForward4:
  379. rate = 4.0;
  380. hint = VLCTransportBarHintScanForward;
  381. break;
  382. case VLCPlayerScanStateNone:
  383. default:
  384. rate = self.scanSavedPlaybackRate.floatValue ?: 1.0;
  385. hint = VLCTransportBarHintNone;
  386. self.scanSavedPlaybackRate = nil;
  387. break;
  388. }
  389. [VLCPlaybackController sharedInstance].playbackRate = rate;
  390. [self.transportBar setHint:hint];
  391. }
  392. #pragma mark -
  393. - (void)updateTimeLabelsForScrubbingFraction:(CGFloat)scrubbingFraction
  394. {
  395. VLCTransportBar *bar = self.transportBar;
  396. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  397. // MAX 1, _ is ugly hack to prevent --:-- instead of 00:00
  398. int scrubbingTimeInt = MAX(1,vpc.mediaDuration*scrubbingFraction);
  399. VLCTime *scrubbingTime = [VLCTime timeWithInt:scrubbingTimeInt];
  400. bar.markerTimeLabel.text = [scrubbingTime stringValue];
  401. VLCTime *remainingTime = [VLCTime timeWithInt:-(int)(vpc.mediaDuration-scrubbingTime.intValue)];
  402. bar.remainingTimeLabel.text = [remainingTime stringValue];
  403. }
  404. - (void)startScrubbing
  405. {
  406. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  407. self.transportBar.scrubbing = YES;
  408. [self updateDimmingView];
  409. if (vpc.isPlaying) {
  410. [vpc playPause];
  411. }
  412. }
  413. - (void)stopScrubbing
  414. {
  415. self.transportBar.scrubbing = NO;
  416. [self updateDimmingView];
  417. VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
  418. [vpc.mediaPlayer play];
  419. }
  420. - (void)updateDimmingView
  421. {
  422. BOOL shouldBeVisible = self.transportBar.scrubbing;
  423. BOOL isVisible = self.dimmingView.alpha == 1.0;
  424. if (shouldBeVisible != isVisible) {
  425. [UIView animateWithDuration:0.3 animations:^{
  426. self.dimmingView.alpha = shouldBeVisible ? 1.0 : 0.0;
  427. }];
  428. }
  429. }
  430. - (void)updateActivityIndicatorForState:(VLCMediaPlayerState)state {
  431. UIActivityIndicatorView *indicator = self.activityIndicator;
  432. switch (state) {
  433. case VLCMediaPlayerStateBuffering:
  434. if (!indicator.isAnimating) {
  435. self.activityIndicator.alpha = 1.0;
  436. [self.activityIndicator startAnimating];
  437. }
  438. break;
  439. default:
  440. if (indicator.isAnimating) {
  441. [self.activityIndicator stopAnimating];
  442. self.activityIndicator.alpha = 0.0;
  443. }
  444. break;
  445. }
  446. }
  447. #pragma mark - PlaybackControls
  448. - (void)fireHidePlaybackControlsIfNotPlayingTimer:(NSTimer *)timer
  449. {
  450. BOOL playing = [[VLCPlaybackController sharedInstance] isPlaying];
  451. if (playing) {
  452. [self animatePlaybackControlsToVisibility:NO];
  453. }
  454. }
  455. - (void)showPlaybackControlsIfNeededForUserInteraction
  456. {
  457. if (self.bottomOverlayView.alpha == 0.0) {
  458. [self animatePlaybackControlsToVisibility:YES];
  459. }
  460. [self hidePlaybackControlsIfNeededAfterDelay];
  461. }
  462. - (void)hidePlaybackControlsIfNeededAfterDelay
  463. {
  464. self.hidePlaybackControlsViewAfterDeleayTimer = [NSTimer scheduledTimerWithTimeInterval:3.0
  465. target:self
  466. selector:@selector(fireHidePlaybackControlsIfNotPlayingTimer:)
  467. userInfo:nil repeats:NO];
  468. }
  469. - (void)animatePlaybackControlsToVisibility:(BOOL)visible
  470. {
  471. NSTimeInterval duration = visible ? 0.3 : 1.0;
  472. CGFloat alpha = visible ? 1.0 : 0.0;
  473. [UIView animateWithDuration:duration
  474. animations:^{
  475. self.bottomOverlayView.alpha = alpha;
  476. }];
  477. }
  478. #pragma mark - Properties
  479. - (void)setHidePlaybackControlsViewAfterDeleayTimer:(NSTimer *)hidePlaybackControlsViewAfterDeleayTimer {
  480. [_hidePlaybackControlsViewAfterDeleayTimer invalidate];
  481. _hidePlaybackControlsViewAfterDeleayTimer = hidePlaybackControlsViewAfterDeleayTimer;
  482. }
  483. - (VLCPlaybackInfoTVViewController *)infoViewController
  484. {
  485. if (!_infoViewController) {
  486. _infoViewController = [[VLCPlaybackInfoTVViewController alloc] initWithNibName:nil bundle:nil];
  487. }
  488. return _infoViewController;
  489. }
  490. #pragma mark - playback controller delegation
  491. - (void)prepareForMediaPlayback:(VLCPlaybackController *)controller
  492. {
  493. APLog(@"%s", __PRETTY_FUNCTION__);
  494. }
  495. - (void)playbackDidStop:(NSNotification *)aNotification
  496. {
  497. [self dismissViewControllerAnimated:YES completion:nil];
  498. }
  499. - (void)mediaPlayerStateChanged:(VLCMediaPlayerState)currentState
  500. isPlaying:(BOOL)isPlaying
  501. currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
  502. currentMediaHasChapters:(BOOL)currentMediaHasChapters
  503. forPlaybackController:(VLCPlaybackController *)controller
  504. {
  505. [self updateActivityIndicatorForState:currentState];
  506. if (controller.isPlaying) {
  507. [self hidePlaybackControlsIfNeededAfterDelay];
  508. } else {
  509. [self showPlaybackControlsIfNeededForUserInteraction];
  510. }
  511. if (controller.isPlaying && !self.bufferingLabel.hidden) {
  512. [UIView animateWithDuration:.3 animations:^{
  513. self.bufferingLabel.hidden = YES;
  514. }];
  515. }
  516. }
  517. - (void)displayMetadataForPlaybackController:(VLCPlaybackController *)controller
  518. title:(NSString *)title
  519. artwork:(UIImage *)artwork
  520. artist:(NSString *)artist
  521. album:(NSString *)album
  522. audioOnly:(BOOL)audioOnly
  523. {
  524. self.titleLabel.text = title;
  525. }
  526. #pragma mark -
  527. - (void)playbackPositionUpdated:(VLCPlaybackController *)controller
  528. {
  529. VLCMediaPlayer *mediaPlayer = controller.mediaPlayer;
  530. // FIXME: hard coded state since the state in mediaPlayer is incorrectly still buffering
  531. [self updateActivityIndicatorForState:VLCMediaPlayerStatePlaying];
  532. VLCTransportBar *transportBar = self.transportBar;
  533. transportBar.remainingTimeLabel.text = [[mediaPlayer remainingTime] stringValue];
  534. transportBar.markerTimeLabel.text = [[mediaPlayer time] stringValue];
  535. transportBar.playbackFraction = mediaPlayer.position;
  536. }
  537. #pragma mark - gesture recognizer delegate
  538. - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
  539. if ([gestureRecognizer.allowedPressTypes containsObject:@(UIPressTypeMenu)]) {
  540. return self.transportBar.scrubbing;
  541. }
  542. return YES;
  543. }
  544. - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
  545. {
  546. return YES;
  547. }
  548. @end
  549. @implementation VLCFullscreenMovieTVViewController (UIViewControllerTransitioningDelegate)
  550. - (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
  551. {
  552. return [[VLCPlaybackInfoTVTransitioningAnimator alloc] init];
  553. }
  554. - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
  555. {
  556. return [[VLCPlaybackInfoTVTransitioningAnimator alloc] init];
  557. }
  558. @end