Advertisement
Guest User

UIViewController

a guest
Jul 18th, 2014
486
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. /* Asset keys */
  3. NSString * const kTracksKeyT         = @"tracks";
  4. NSString * const kPlayableKeyT      = @"playable";
  5.  
  6. /* PlayerItem keys */
  7. NSString * const kStatusKeyT         = @"status";
  8.  
  9. /* AVPlayer keys */
  10. NSString * const kRateKeyT          = @"rate";
  11. NSString * const kCurrentItemKeyT   = @"currentItem";
  12.  
  13. /* Custom keys for displaying ads on Madness View*/
  14. NSString * const kReadyForAdDisplayKeyT = @"readyForDisplay";
  15.  
  16. static void *AVPlayerDemoPlaybackViewControllerRateObservationContext = &AVPlayerDemoPlaybackViewControllerRateObservationContext;
  17. static void *AVPlayerDemoPlaybackViewControllerStatusObservationContext = &AVPlayerDemoPlaybackViewControllerStatusObservationContext;
  18. static void *AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext = &AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext;
  19. static void *AVPlayerDemoPlaybackViewControllerCurrentItemObservationContextForDisplay = &AVPlayerDemoPlaybackViewControllerCurrentItemObservationContextForDisplay;
  20.  
  21. #define kMaxIdleTimeSeconds 5.0
  22.  
  23. @interface LFVideoPlayerViewController (){
  24.  
  25.     AVPlayer            *_player;
  26.     AVPlayerItem        *_playerItem;
  27.     NSURL               *_URL;
  28.    
  29.     id mTimeObserver;
  30.     float mRestoreAfterScrubbingRate;
  31.     BOOL seekToZeroBeforePlay;
  32.    
  33.     BOOL controlsHidden;
  34.    
  35.     UITapGestureRecognizer *_tapGestureRecognizer;
  36.    
  37.     NSTimer *idleTimer;
  38. }
  39.  
  40. @end
  41.  
  42. @implementation LFVideoPlayerViewController
  43.  
  44. - (void)initialize
  45. {
  46.    
  47. }
  48.  
  49. - (id)init
  50. {
  51.     self = [super init];
  52.     if (self) {
  53.         // Initialize self
  54.         [self initialize];
  55.     }
  56.     return self;
  57. }
  58.  
  59. - (id)initWithCoder:(NSCoder *)aDecoder
  60. {
  61.     self = [super initWithCoder:aDecoder];
  62.     if (self) {
  63.         // Initialize self
  64.         [self initialize];
  65.     }
  66.     return self;
  67. }
  68.  
  69. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  70. {
  71.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  72.     if (self) {
  73.         // Initialize self
  74.         [self initialize];
  75.     }
  76.     return self;
  77. }
  78.  
  79. - (void)viewDidLoad
  80. {
  81.     [self.progressSlider addTarget:self action:@selector(progressSliderChanged:) forControlEvents:UIControlEventValueChanged];
  82.  
  83.     [self setPlayer:nil];
  84.     [self.madnessView setVideoId:self.videoId];
  85.  
  86.     UIImage *maxImage = [[UIImage imageNamed:@"slider_empty.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 8, 0, 8)];
  87.     UIImage *minImage = [[UIImage imageNamed:@"slider_filled.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 8, 0, 8)];
  88.  
  89.     [self.progressSlider setMaximumTrackImage:maxImage forState:UIControlStateNormal];
  90.     [self.progressSlider setMinimumTrackImage:minImage forState:UIControlStateNormal];
  91.     [self.progressSlider setThumbImage:[UIImage imageNamed:@"slider.png"] forState:UIControlStateNormal];
  92.  
  93.     [self setupViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
  94.  
  95.     _tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(controlsViewClicked:)];
  96.     [self.controlsView addGestureRecognizer:_tapGestureRecognizer];
  97.  
  98.     [super viewDidLoad];
  99. }
  100.  
  101. -(void) viewWillDisappear:(BOOL)animated
  102. {
  103.     [super viewWillDisappear:animated];
  104.  
  105.     if(_player.rate == 1.0){
  106.         [_player pause];
  107.     }
  108.  
  109.     [idleTimer invalidate];
  110.  
  111.     if(mTimeObserver){
  112.         [_player removeTimeObserver:mTimeObserver];
  113.         mTimeObserver = nil;
  114.     }
  115.     [_playerItem removeObserver:self forKeyPath:kStatusKeyT];
  116.     [[NSNotificationCenter defaultCenter] removeObserver:self
  117.                                                     name:AVPlayerItemDidPlayToEndTimeNotification
  118.                                                   object:_playerItem];
  119.  
  120.    
  121.     _player = nil;
  122.     _playerItem = nil;
  123.     idleTimer = nil;
  124.     _tapGestureRecognizer = nil;
  125. }
  126.  
  127. -(void) dealloc
  128. {
  129.     NSLog(@"DEALLOCING");
  130. }
  131.  
  132. -(void) hideControlsAnimated:(BOOL) animated
  133. {
  134.     if (self.navigationController.navigationBar.hidden == NO)
  135.     {
  136.         // hide the Navigation Bar
  137.         [self.navigationController setNavigationBarHidden:YES animated:YES];
  138.         [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
  139.         [UIView animateWithDuration:0.2f animations:
  140.              ^{
  141.                  [self._controlsBar setTransform:CGAffineTransformMakeTranslation(0.f, CGRectGetHeight([self._controlsBar bounds]))];
  142.              } completion:
  143.              ^(BOOL finished)
  144.              {
  145.                  [self._controlsBar setHidden:YES];
  146.              }
  147.         ];
  148.     }
  149. }
  150.  
  151. -(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
  152.     [self setupViewsForOrientation:toInterfaceOrientation];
  153. }
  154.  
  155. -(void) setupViewsForOrientation:(UIInterfaceOrientation) toInterfaceOrientation
  156. {
  157.     if(UIInterfaceOrientationIsLandscape(toInterfaceOrientation)){
  158.         UIButton *temp = [[UIButton alloc] initWithFrame:CGRectMake(0,0, 28, 28)];
  159.         [temp setImage:[UIImage imageNamed:@"btn_back.png"] forState:UIControlStateNormal];
  160.         [temp addTarget:self action:@selector(doneDidTouch:) forControlEvents:UIControlEventTouchUpInside];
  161.  
  162.         UIBarButtonItem *leftButtonTemp = [[UIBarButtonItem alloc] initWithCustomView:temp];
  163.         self.navigationItem.leftBarButtonItem = leftButtonTemp;
  164.     }
  165.     else{
  166.         UIButton *temp = [[UIButton alloc] initWithFrame:CGRectMake(0,0, 30, 30)];
  167.         [temp setImage:[UIImage imageNamed:@"btn_back.png"] forState:UIControlStateNormal];
  168.         [temp addTarget:self action:@selector(doneDidTouch:) forControlEvents:UIControlEventTouchUpInside];
  169.  
  170.         UIBarButtonItem *leftButtonTemp = [[UIBarButtonItem alloc] initWithCustomView:temp];
  171.         self.navigationItem.leftBarButtonItem = leftButtonTemp;
  172.     }
  173. }
  174.  
  175. #pragma mark - Actions
  176.  
  177. -(void) controlsViewClicked:(UIGestureRecognizer *)gestureRecognizer
  178. {
  179.     CGPoint loc = [gestureRecognizer locationInView:self.controlsView];
  180.     if([self.madnessView adClicked:loc]){
  181.        
  182.     }
  183.     else{
  184.         if (self.navigationController.navigationBar.hidden == YES)
  185.         {
  186.             // hide the Navigation Bar
  187.             [self.navigationController setNavigationBarHidden:NO animated:YES];
  188.             [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
  189.             [self._controlsBar setHidden:NO];
  190.             [UIView animateWithDuration:0.2f animations:
  191.              ^{
  192.                  [self._controlsBar setTransform:CGAffineTransformMakeTranslation(0.f, CGRectGetHeight([self._controlsBar bounds])-50)];
  193.              } completion:
  194.              ^(BOOL finished)
  195.              {
  196.                  
  197.              }
  198.              ];
  199.         }
  200.         else if (self.navigationController.navigationBar.hidden == NO)
  201.         {
  202.             // hide the Navigation Bar
  203.             [self.navigationController setNavigationBarHidden:YES animated:YES];
  204.             [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
  205.             [UIView animateWithDuration:0.2f animations:
  206.              ^{
  207.                  [self._controlsBar setTransform:CGAffineTransformMakeTranslation(0.f, CGRectGetHeight([self._controlsBar bounds]))];
  208.              } completion:
  209.              ^(BOOL finished)
  210.              {
  211.                  [self._controlsBar setHidden:YES];
  212.              }
  213.              ];
  214.         }
  215.     }
  216. }
  217.  
  218. - (void)doneDidTouch:(id)sender
  219. {
  220.     [NSObject cancelPreviousPerformRequestsWithTarget:self];
  221.     [_player pause];
  222.    
  223.     [[self navigationController] popToRootViewControllerAnimated:YES];
  224. }
  225.  
  226. - (IBAction)playButtonPressed:(id)sender {
  227.     /* If we are at the end of the movie, we must seek to the beginning first
  228.      before starting playback. */
  229.     if (YES == seekToZeroBeforePlay)
  230.     {
  231.         seekToZeroBeforePlay = NO;
  232.         [_player seekToTime:kCMTimeZero];
  233.     }
  234.    
  235.     [_player play];
  236.    
  237.     [self showStopButton];
  238. }
  239.  
  240. - (IBAction)pauseButtonPressed:(id)sender {
  241.     [_player pause];
  242.    
  243.     [self showPlayButton];
  244. }
  245.  
  246. - (IBAction)zoomButtonPressed:(id)sender {
  247.     if([[self.playbackView getVideoFillMode] isEqualToString:@"AVLayerVideoGravityResizeAspect"]){
  248.         [self.playbackView setVideoFillMode:@"AVLayerVideoGravityResizeAspectFill"];
  249.         [self.madnessView setVideoGravity:@"AVLayerVideoGravityResizeAspectFill"];
  250.         [self.zoomButton setImage:[UIImage imageNamed:@"btn_zoomOut.png"] forState:UIControlStateNormal];
  251.     }
  252.     else{
  253.         [self.playbackView setVideoFillMode:@"AVLayerVideoGravityResizeAspect"];
  254.         [self.madnessView setVideoGravity:@"AVLayerVideoGravityResizeAspect"];
  255.         [self.zoomButton setImage:[UIImage imageNamed:@"btn_zoomIn.png"] forState:UIControlStateNormal];
  256.     }
  257. }
  258.  
  259. - (void)progressSliderChanged:(id)sender
  260. {
  261.     seekToZeroBeforePlay = NO;
  262.     [self resetIdleTimer];
  263.     float duration = CMTimeGetSeconds([_playerItem duration]);
  264.     CMTime seekTo = CMTimeMakeWithSeconds(duration * _progressSlider.value, NSEC_PER_SEC);
  265.     [_player seekToTime:seekTo];
  266. }
  267.  
  268. - (void)forwardDidTouch:(id)sender
  269. {
  270.     float current_time = CMTimeGetSeconds([_player currentTime]);
  271.     CMTime seekTo =  CMTimeMakeWithSeconds(current_time + 10, NSEC_PER_SEC);
  272.     [_player seekToTime:seekTo];
  273. }
  274.  
  275. - (void)rewindDidTouch:(id)sender
  276. {
  277.     float current_time = CMTimeGetSeconds([_player currentTime]);
  278.     CMTime seekTo =  CMTimeMakeWithSeconds(current_time - 10, NSEC_PER_SEC);
  279.     [_player seekToTime:seekTo];
  280. }
  281.  
  282.  
  283. #pragma mark Asset URL
  284.  
  285. -(void) setURL:(NSURL*) URL
  286. {
  287.     if (_URL != URL)
  288.     {
  289.         _URL = [URL copy];
  290.         /*
  291.          Create an asset for inspection of a resource referenced by a given URL.
  292.          Load the values for the asset keys "tracks", "playable".
  293.          */
  294.         AVURLAsset *asset = [AVURLAsset URLAssetWithURL:_URL options:nil];
  295.        
  296.         NSArray *requestedKeys = [NSArray arrayWithObjects:kTracksKeyT, kPlayableKeyT, nil];
  297.        
  298.         /* Tells the asset to load the values of any of the specified keys that are not already loaded. */
  299.         [asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:
  300.          ^{
  301.              dispatch_async( dispatch_get_main_queue(),
  302.                             ^{
  303.                                 /* IMPORTANT: Must dispatch to main queue in order to operate on the AVPlayer and AVPlayerItem. */
  304.                                 [self prepareToPlayAsset:asset withKeys:requestedKeys];
  305.                             });
  306.          }];
  307.     }
  308. }
  309.  
  310. - (NSURL*)URL
  311. {
  312.     return _URL;
  313. }
  314.  
  315. #pragma mark - ASSET PREPARE TO PLAY
  316.  
  317. -(void) setPlayer:(AVPlayer*) player
  318. {
  319.     _player = player;
  320. }
  321.  
  322. /*
  323.  Invoked at the completion of the loading of the values for all keys on the asset that we require.
  324.  Checks whether loading was successfull and whether the asset is playable.
  325.  If so, sets up an AVPlayerItem and an AVPlayer to play the asset.
  326.  */
  327. - (void)prepareToPlayAsset:(AVURLAsset *)asset withKeys:(NSArray *)requestedKeys
  328. {
  329.     /* Make sure that the value of each key has loaded successfully. */
  330.     for (NSString *thisKey in requestedKeys)
  331.     {
  332.         NSError *error = nil;
  333.         AVKeyValueStatus keyStatus = [asset statusOfValueForKey:thisKey error:&error];
  334.         if (keyStatus == AVKeyValueStatusFailed)
  335.         {
  336.             [self assetFailedToPrepareForPlayback:error];
  337.             return;
  338.         }
  339.         /* If you are also implementing -[AVAsset cancelLoading], add your code here to bail out properly in the case of cancellation. */
  340.     }
  341.    
  342.     /* Use the AVAsset playable property to detect whether the asset can be played. */
  343.     if (!asset.playable)
  344.     {
  345.         /* Generate an error describing the failure. */
  346.         NSString *localizedDescription = NSLocalizedString(@"Item cannot be played", @"Item cannot be played description");
  347.         NSString *localizedFailureReason = NSLocalizedString(@"The assets tracks were loaded, but could not be made playable.", @"Item cannot be played failure reason");
  348.         NSDictionary *errorDict = [NSDictionary dictionaryWithObjectsAndKeys:
  349.                                    localizedDescription, NSLocalizedDescriptionKey,
  350.                                    localizedFailureReason, NSLocalizedFailureReasonErrorKey,
  351.                                    nil];
  352.         NSError *assetCannotBePlayedError = [NSError errorWithDomain:@"StitchedStreamPlayer" code:0 userInfo:errorDict];
  353.        
  354.         /* Display the error to the user. */
  355.         [self assetFailedToPrepareForPlayback:assetCannotBePlayedError];
  356.        
  357.         return;
  358.     }
  359.    
  360.     /* At this point we're ready to set up for playback of the asset. */
  361.    
  362.     /* Stop observing our prior AVPlayerItem, if we have one. */
  363.     if (_playerItem)
  364.     {
  365.         /* Remove existing player item key value observers and notifications. */
  366.  
  367.         [_playerItem removeObserver:self forKeyPath:kStatusKeyT];
  368.        
  369.         [[NSNotificationCenter defaultCenter] removeObserver:self
  370.                                                         name:AVPlayerItemDidPlayToEndTimeNotification
  371.                                                       object:_playerItem];
  372.     }
  373.    
  374.     /* Create a new instance of AVPlayerItem from the now successfully loaded AVAsset. */
  375.     _playerItem = [AVPlayerItem playerItemWithAsset:asset];
  376.    
  377.     /* Observe the player item "status" key to determine when it is ready to play. */
  378.     [_playerItem addObserver:self
  379.                        forKeyPath:kStatusKeyT
  380.                           options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
  381.                           context:AVPlayerDemoPlaybackViewControllerStatusObservationContext];
  382.    
  383.     /* When the player item has played to its end time we'll toggle
  384.      the movie controller Pause button to be the Play button */
  385.     [[NSNotificationCenter defaultCenter] addObserver:self
  386.                                              selector:@selector(playerItemDidReachEnd:)
  387.                                                  name:AVPlayerItemDidPlayToEndTimeNotification
  388.                                                object:_playerItem];
  389.    
  390.     //TODO
  391.     seekToZeroBeforePlay = NO;
  392.    
  393.     /* Create new player, if we don't already have one. */
  394.     if (!_player)
  395.     {
  396.         /* Get a new AVPlayer initialized to play the specified player item. */
  397.         [self setPlayer:[AVPlayer playerWithPlayerItem:_playerItem]];
  398.        
  399.         /* Observe the AVPlayer "currentItem" property to find out when any
  400.          AVPlayer replaceCurrentItemWithPlayerItem: replacement will/did
  401.          occur.*/
  402.         [_player addObserver:self
  403.                       forKeyPath:kCurrentItemKeyT
  404.                          options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
  405.                          context:AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext];
  406.        
  407.         /* Observe the AVPlayer "rate" property to update the scrubber control. */
  408.         [_player addObserver:self
  409.                       forKeyPath:kRateKeyT
  410.                          options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
  411.                          context:AVPlayerDemoPlaybackViewControllerRateObservationContext];
  412.     }
  413.    
  414.     //    AVPlayerLayer *playerLayer = [[AVPlayerLayer alloc] init];
  415.     //    [playerLayer setPlayer:self.player];
  416.     //    [playerLayer setFrame:self.mPlaybackView.layer.bounds];
  417.     //    [self.mPlaybackView.layer addSublayer:playerLayer];
  418.     [self.playbackView.layer addObserver:self forKeyPath:kReadyForAdDisplayKeyT
  419.                                   options:NSKeyValueObservingOptionInitial context:AVPlayerDemoPlaybackViewControllerCurrentItemObservationContextForDisplay];
  420.    
  421.     /* Make our new AVPlayerItem the AVPlayer's current item. */
  422.     if (_player.currentItem != _playerItem)
  423.     {
  424.         /* Replace the player item with a new player item. The item replacement occurs
  425.          asynchronously; observe the currentItem property to find out when the
  426.          replacement will/did occur*/
  427.         [_player replaceCurrentItemWithPlayerItem:_playerItem];
  428.        
  429.         [self syncPlayPauseButtons];
  430.     }
  431.    
  432.     [self.progressSlider setValue:0.0];
  433. }
  434.  
  435. #pragma mark -
  436. #pragma mark Loading the Asset Keys Asynchronously
  437.  
  438. #pragma mark -
  439. #pragma mark Error Handling - Preparing Assets for Playback Failed
  440.  
  441. /* --------------------------------------------------------------
  442.  **  Called when an asset fails to prepare for playback for any of
  443.  **  the following reasons:
  444.  **
  445.  **  1) values of asset keys did not load successfully,
  446.  **  2) the asset keys did load successfully, but the asset is not
  447.  **     playable
  448.  **  3) the item did not become ready to play.
  449.  ** ----------------------------------------------------------- */
  450.  
  451. -(void)assetFailedToPrepareForPlayback:(NSError *)error
  452. {
  453.     [self removePlayerTimeObserver];
  454.     [self syncScrubber];
  455.     [self disableScrubber];
  456.     [self disablePlayerButtons];
  457.    
  458.     /* Display the error. */
  459.     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[error localizedDescription]
  460.                                                         message:[error localizedFailureReason]
  461.                                                        delegate:nil
  462.                                               cancelButtonTitle:@"OK"
  463.                                               otherButtonTitles:nil];
  464.     [alertView show];
  465. }
  466.  
  467. #pragma mark Player Item
  468.  
  469. - (BOOL)isPlaying
  470. {
  471.     return mRestoreAfterScrubbingRate != 0.f || [_player rate] != 0.f;
  472. }
  473.  
  474. /* Called when the player item has played to its end time. */
  475. - (void)playerItemDidReachEnd:(NSNotification *)notification
  476. {
  477.     /* After the movie has played to its end time, seek back to time zero
  478.      to play it again. */
  479.     seekToZeroBeforePlay = YES;
  480. }
  481. /* ---------------------------------------------------------
  482.  **  Get the duration for a AVPlayerItem.
  483.  ** ------------------------------------------------------- */
  484.  
  485. - (CMTime)playerItemDuration
  486. {
  487.     AVPlayerItem *playerItem = [_player currentItem];
  488.     if (playerItem.status == AVPlayerItemStatusReadyToPlay)
  489.     {
  490.         /*
  491.          NOTE:
  492.          Because of the dynamic nature of HTTP Live Streaming Media, the best practice
  493.          for obtaining the duration of an AVPlayerItem object has changed in iOS 4.3.
  494.          Prior to iOS 4.3, you would obtain the duration of a player item by fetching
  495.          the value of the duration property of its associated AVAsset object. However,
  496.          note that for HTTP Live Streaming Media the duration of a player item during
  497.          any particular playback session may differ from the duration of its asset. For
  498.          this reason a new key-value observable duration property has been defined on
  499.          AVPlayerItem.
  500.          
  501.          See the AV Foundation Release Notes for iOS 4.3 for more information.
  502.          */
  503.         return([playerItem duration]);
  504.     }
  505.    
  506.     return(kCMTimeInvalid);
  507. }
  508.  
  509. /* Cancels the previously registered time observer. */
  510. -(void)removePlayerTimeObserver
  511. {
  512.     if (mTimeObserver)
  513.     {
  514.         [_player removeTimeObserver:mTimeObserver];
  515.         mTimeObserver = nil;
  516.     }
  517. }
  518.  
  519. #pragma mark -  Movie scrubber control
  520.  
  521. /* ---------------------------------------------------------
  522.  **  Methods to handle manipulation of the movie scrubber control
  523.  ** ------------------------------------------------------- */
  524.  
  525. /* Requests invocation of a given block during media playback to update the movie scrubber control. */
  526. -(void)initScrubberTimer
  527. {
  528.    
  529.     double interval = .1f;
  530.     NSLog(@"Seconds: %f", CMTimeGetSeconds([self playerItemDuration]));
  531.     CMTime playerDuration = [self playerItemDuration];
  532.     if (CMTIME_IS_INVALID(playerDuration))
  533.     {
  534.         return;
  535.     }
  536.     double duration = CMTimeGetSeconds(playerDuration);
  537.     if (isfinite(duration))
  538.     {
  539.         CGFloat width = CGRectGetWidth([self.progressSlider bounds]);
  540.         interval = 0.5f * duration / width;
  541.     }
  542.     __weak typeof(self) weakSelf = self;
  543.     /* Update the scrubber during normal playback. */
  544.     mTimeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(interval, NSEC_PER_SEC)
  545.                                                                queue:NULL /* If you pass NULL, the main queue is used. */
  546.                                                           usingBlock:^(CMTime time)
  547.                      {
  548.                          __strong typeof(self) strongSelf = weakSelf;
  549.                          [strongSelf syncScrubber];
  550.                      }];
  551. }
  552.  
  553. /* Set the scrubber based on the player current time. */
  554. - (void)syncScrubber
  555. {
  556.     CMTime playerDuration = [self playerItemDuration];
  557.     if (CMTIME_IS_INVALID(playerDuration))
  558.     {
  559.         _progressSlider.minimumValue = 0.0;
  560.         return;
  561.     }
  562.    
  563.     double duration = CMTimeGetSeconds(playerDuration);
  564.     if (isfinite(duration))
  565.     {
  566.         float minValue = [self.progressSlider minimumValue];
  567.         float maxValue = [self.progressSlider maximumValue];
  568.         double time = CMTimeGetSeconds([_player currentTime]);
  569.        
  570.         [self.progressSlider setValue:(maxValue - minValue) * time / duration + minValue];
  571.     }
  572. }
  573.  
  574. -(void)enableScrubber
  575. {
  576.     self.progressSlider.enabled = YES;
  577. }
  578.  
  579. -(void)disableScrubber
  580. {
  581.     self.progressSlider.enabled = NO;
  582. }
  583.  
  584.  
  585. #pragma mark -
  586. #pragma mark Asset Key Value Observing
  587. #pragma mark
  588.  
  589. #pragma mark Key Value Observer for player rate, currentItem, player item status
  590.  
  591. /* ---------------------------------------------------------
  592.  **  Called when the value at the specified key path relative
  593.  **  to the given object has changed.
  594.  **  Adjust the movie play and pause button controls when the
  595.  **  player item "status" value changes. Update the movie
  596.  **  scrubber control when the player item is ready to play.
  597.  **  Adjust the movie scrubber control when the player item
  598.  **  "rate" value changes. For updates of the player
  599.  **  "currentItem" property, set the AVPlayer for which the
  600.  **  player layer displays visual output.
  601.  **  NOTE: this method is invoked on the main queue.
  602.  ** ------------------------------------------------------- */
  603.  
  604. - (void)observeValueForKeyPath:(NSString*) path
  605.                       ofObject:(id)object
  606.                         change:(NSDictionary*)change
  607.                        context:(void*)context
  608. {
  609.     /* AVPlayerItem "status" property value observer. */
  610.     if (context == AVPlayerDemoPlaybackViewControllerStatusObservationContext)
  611.     {
  612.         [self syncPlayPauseButtons];
  613.        
  614.         AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
  615.         switch (status)
  616.         {
  617.                 /* Indicates that the status of the player is not yet known because
  618.                  it has not tried to load new media resources for playback */
  619.             case AVPlayerStatusUnknown:
  620.             {
  621.                 [self removePlayerTimeObserver];
  622.                 [self syncScrubber];
  623.                
  624.                 [self disableScrubber];
  625.                 [self disablePlayerButtons];
  626.             }
  627.                 break;
  628.                
  629.             case AVPlayerStatusReadyToPlay:
  630.             {
  631.                 /* Once the AVPlayerItem becomes ready to play, i.e.
  632.                  [playerItem status] == AVPlayerItemStatusReadyToPlay,
  633.                  its duration can be fetched from the item. */
  634.                
  635.                 [self initScrubberTimer];
  636.                
  637.                 [self enableScrubber];
  638.                 [self enablePlayerButtons];
  639.             }
  640.                 break;
  641.                
  642.             case AVPlayerStatusFailed:
  643.             {
  644.                 AVPlayerItem *playerItem = (AVPlayerItem *)object;
  645.                 [self assetFailedToPrepareForPlayback:playerItem.error];
  646.             }
  647.                 break;
  648.         }
  649.     }
  650.     /* AVPlayer "rate" property value observer. */
  651.     else if (context == AVPlayerDemoPlaybackViewControllerRateObservationContext)
  652.     {
  653.         [self syncPlayPauseButtons];
  654.     }
  655.     /* AVPlayer "currentItem" property observer.
  656.      Called when the AVPlayer replaceCurrentItemWithPlayerItem:
  657.      replacement will/did occur. */
  658.     else if (context == AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext)
  659.     {
  660.         AVPlayerItem *newPlayerItem = [change objectForKey:NSKeyValueChangeNewKey];
  661.        
  662.         /* Is the new player item null? */
  663.         if (newPlayerItem == (id)[NSNull null])
  664.         {
  665.             [self disablePlayerButtons];
  666.             [self disableScrubber];
  667.         }
  668.         else /* Replacement of player currentItem has occurred */
  669.         {
  670.             /* Set the AVPlayer for which the player layer displays visual output. */
  671.             [self.playbackView setPlayer:_player];
  672.            
  673.             /* Specifies that the player should preserve the video’s aspect ratio and
  674.              fit the video within the layer’s bounds. */
  675.             [self.playbackView setVideoFillMode:AVLayerVideoGravityResizeAspect];
  676.            
  677.             [self syncPlayPauseButtons];
  678.         }
  679.     }
  680.     else if( context == AVPlayerDemoPlaybackViewControllerCurrentItemObservationContextForDisplay)
  681.     {
  682.         AVPlayerLayer *layer = (AVPlayerLayer*) object;
  683.         if (layer.readyForDisplay){
  684.             [layer removeObserver:self forKeyPath:kReadyForAdDisplayKeyT];
  685.            
  686.             AVPlayerItem *item = _player.currentItem;
  687.             AVSynchronizedLayer *syncedLayer = [AVSynchronizedLayer synchronizedLayerWithPlayerItem:item];
  688.             syncedLayer.frame = CGRectMake(0, 0, 568, 320);
  689.             syncedLayer.backgroundColor = [[UIColor clearColor] CGColor];
  690.             [self.madnessView addSyncedLayer:syncedLayer player:[self.playbackView player] withGravity:layer.videoGravity];
  691.         }
  692.     }
  693.     else
  694.     {
  695.         [super observeValueForKeyPath:path ofObject:object change:change context:context];
  696.     }
  697. }
  698.  
  699. #pragma mark -
  700. #pragma mark Play, Stop buttons
  701.  
  702. /* Show the stop button in the movie player controller. */
  703. -(void)showStopButton
  704. {
  705.     self.playButton.hidden = YES;
  706.     self.pauseButton.hidden = NO;
  707. }
  708.  
  709. /* Show the play button in the movie player controller. */
  710. -(void)showPlayButton
  711. {
  712.     self.pauseButton.hidden = YES;
  713.     self.playButton.hidden = NO;
  714. }
  715.  
  716. /* If the media is playing, show the stop button; otherwise, show the play button. */
  717. - (void)syncPlayPauseButtons
  718. {
  719.     if ([self isPlaying])
  720.     {
  721.         [self showStopButton];
  722.     }
  723.     else
  724.     {
  725.         [self showPlayButton];
  726.     }
  727. }
  728.  
  729. -(void)enablePlayerButtons
  730. {
  731.     _playButton.enabled = YES;
  732.     _pauseButton.enabled = YES;
  733. }
  734.  
  735. -(void)disablePlayerButtons
  736. {
  737.     _playButton.enabled = NO;
  738.     _pauseButton.enabled = NO;
  739. }
  740.  
  741. #pragma mark -
  742. #pragma mark Handling idle timeout
  743.  
  744. - (void)resetIdleTimer {
  745.     if (!idleTimer) {
  746.         idleTimer = [NSTimer scheduledTimerWithTimeInterval:kMaxIdleTimeSeconds
  747.                                                       target:self
  748.                                                     selector:@selector(idleTimerExceeded)
  749.                                                     userInfo:nil
  750.                                                      repeats:NO];
  751.     }
  752.     else {
  753.         if (fabs([idleTimer.fireDate timeIntervalSinceNow]) < kMaxIdleTimeSeconds-1.0) {
  754.             [idleTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:kMaxIdleTimeSeconds]];
  755.         }
  756.     }
  757. }
  758.  
  759. - (void)idleTimerExceeded {
  760.     idleTimer = nil;
  761.     [self hideControlsAnimated:YES];
  762.     [self resetIdleTimer];
  763. }
  764.  
  765. - (UIResponder *)nextResponder {
  766.     [self resetIdleTimer];
  767.     return [super nextResponder];
  768. }
  769.  
  770. @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement