Commit 654ae1a2 authored by Stanisław Chmiela's avatar Stanisław Chmiela
Browse files

Merge pull request #199 from sjchmiela/feature/additional_playback_callbacks

Additional playback callbacks
parents 3ebda023 e35eaf64
Loading
Loading
Loading
Loading
+47 −6
Changes for RCTVideo.m: 47 added lines, 6 removed lines.
Original line number Diff line number Diff line
@@ -7,6 +7,8 @@
static NSString *const statusKeyPath = @"status";
static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp";
static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
static NSString *const readyForDisplayKeyPath = @"readyForDisplay";
static NSString *const playbackRate = @"rate";

@implementation RCTVideo
{
@@ -36,6 +38,7 @@ static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
  BOOL _muted;
  BOOL _paused;
  BOOL _repeat;
  BOOL _playbackStalled;
  NSString * _resizeMode;
  BOOL _fullscreenPlayerPresented;
  UIViewController * _presentingViewController;
@@ -46,6 +49,7 @@ static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
  if ((self = [super init])) {
    _eventDispatcher = eventDispatcher;

    _playbackStalled = NO;
    _rate = 1.0;
    _volume = 1.0;
    _resizeMode = @"AVLayerVideoGravityResizeAspectFill";
@@ -213,13 +217,13 @@ static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
  [self addPlayerItemObservers];

  [_player pause];
  [_playerLayer removeFromSuperlayer];
  _playerLayer = nil;
  [self removePlayerLayer];
  [_playerViewController.view removeFromSuperview];
  _playerViewController = nil;

  _player = [AVPlayer playerWithPlayerItem:_playerItem];
  _player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
  [_player addObserver:self forKeyPath:playbackRate options:0 context:nil];

  const Float64 progressUpdateIntervalMS = _progressUpdateInterval / 1000;
  // @see endScrubbing in AVPlayerDemoPlaybackViewController.m of https://developer.apple.com/library/ios/samplecode/AVPlayerDemo/Introduction/Intro.html
@@ -321,6 +325,25 @@ static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
      }
      _playerBufferEmpty = NO;
    }
   } else if (object == _playerLayer) {
      if([keyPath isEqualToString:readyForDisplayKeyPath] && [change objectForKey:NSKeyValueChangeNewKey]) {
        if([change objectForKey:NSKeyValueChangeNewKey]) {
          [_eventDispatcher sendInputEventWithName:@"onReadyForDisplay"
                                              body:@{@"target": self.reactTag}];
        }
    }
  } else if (object == _player) {
      if([keyPath isEqualToString:playbackRate]) {
          [_eventDispatcher sendInputEventWithName:@"onPlaybackRateChange"
                                              body:@{@"playbackRate": [NSNumber numberWithFloat:_player.rate],
                                                     @"target": self.reactTag}];
          if(_playbackStalled && _player.rate > 0) {
              [_eventDispatcher sendInputEventWithName:@"onPlaybackResume"
                                                  body:@{@"playbackRate": [NSNumber numberWithFloat:_player.rate],
                                                         @"target": self.reactTag}];
              _playbackStalled = NO;
          }
      }
  } else {
      [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
  }
@@ -333,6 +356,16 @@ static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
                                           selector:@selector(playerItemDidReachEnd:)
                                               name:AVPlayerItemDidPlayToEndTimeNotification
                                             object:[_player currentItem]];
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(playbackStalled:)
                                               name:AVPlayerItemPlaybackStalledNotification
                                             object:nil];
}

- (void)playbackStalled:(NSNotification *)notification
{
  [_eventDispatcher sendInputEventWithName:@"onPlaybackStalled" body:@{@"target": self.reactTag}];
  _playbackStalled = YES;
}

- (void)playerItemDidReachEnd:(NSNotification *)notification
@@ -518,6 +551,8 @@ static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
      _playerLayer.frame = self.bounds;
      _playerLayer.needsDisplayOnBoundsChange = YES;
        
      [_playerLayer addObserver:self forKeyPath:readyForDisplayKeyPath options:NSKeyValueObservingOptionNew context:nil];
    
      [self.layer addSublayer:_playerLayer];
      self.layer.needsDisplayOnBoundsChange = YES;
    }
@@ -530,8 +565,7 @@ static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
        _controls = controls;
        if( _controls )
        {
            [_playerLayer removeFromSuperlayer];
            _playerLayer = nil;
            [self removePlayerLayer];
            [self usePlayerViewController];
        }
        else
@@ -543,6 +577,13 @@ static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
    }
}

- (void)removePlayerLayer
{
    [_playerLayer removeFromSuperlayer];
    [_playerLayer removeObserver:self forKeyPath:readyForDisplayKeyPath];
    _playerLayer = nil;
}

#pragma mark - RCTVideoPlayerViewControllerDelegate

- (void)videoPlayerViewControllerWillDismiss:(AVPlayerViewController *)playerViewController
@@ -626,10 +667,10 @@ static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
- (void)removeFromSuperview
{
  [_player pause];
  [_player removeObserver:self forKeyPath:playbackRate];
  _player = nil;

  [_playerLayer removeFromSuperlayer];
  _playerLayer = nil;
  [self removePlayerLayer];
  
  [_playerViewController.view removeFromSuperview];
  _playerViewController = nil;
+5 −1
Changes for RCTVideoManager.m: 5 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -28,7 +28,11 @@ RCT_EXPORT_MODULE();
    @"onVideoFullscreenPlayerWillPresent",
    @"onVideoFullscreenPlayerDidPresent",
    @"onVideoFullscreenPlayerWillDismiss",
    @"onVideoFullscreenPlayerDidDismiss"
    @"onVideoFullscreenPlayerDidDismiss",
    @"onReadyForDisplay",
    @"onPlaybackStalled",
    @"onPlaybackResume",
    @"onPlaybackRateChange"
  ];
}

+36 −0
Changes for Video.js: 36 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -38,6 +38,10 @@ export default class Video extends Component {
    this._onFullscreenPlayerDidPresent = this._onFullscreenPlayerDidPresent.bind(this);
    this._onFullscreenPlayerWillDismiss = this._onFullscreenPlayerWillDismiss.bind(this);
    this._onFullscreenPlayerDidDismiss = this._onFullscreenPlayerDidDismiss.bind(this);
    this._onReadyForDisplay = this._onReadyForDisplay.bind(this);
    this._onPlaybackStalled = this._onPlaybackStalled.bind(this);
    this._onPlaybackResume = this._onPlaybackResume.bind(this);
    this._onPlaybackRateChange = this._onPlaybackRateChange.bind(this);
  }

  setNativeProps(nativeProps) {
@@ -120,6 +124,30 @@ export default class Video extends Component {
    }
  }

  _onReadyForDisplay(event) {
    if (this.props.onReadyForDisplay) {
      this.props.onReadyForDisplay(event.nativeEvent);
    }
  }

  _onPlaybackStalled(event) {
    if (this.props.onPlaybackStalled) {
      this.props.onPlaybackStalled(event.nativeEvent);
    }
  }

  _onPlaybackResume(event) {
    if (this.props.onPlaybackResume) {
      this.props.onPlaybackResume(event.nativeEvent);
    }
  }

  _onPlaybackRateChange(event) {
    if (this.props.onPlaybackRateChange) {
      this.props.onPlaybackRateChange(event.nativeEvent);
    }
  }

  render() {
    const {
      source,
@@ -165,6 +193,10 @@ export default class Video extends Component {
      onVideoFullscreenPlayerDidPresent: this._onFullscreenPlayerDidPresent,
      onVideoFullscreenPlayerWillDismiss: this._onFullscreenPlayerWillDismiss,
      onVideoFullscreenPlayerDidDismiss: this._onFullscreenPlayerDidDismiss,
      onReadyForDisplay: this._onReadyForDisplay,
      onPlaybackStalled: this._onPlaybackStalled,
      onPlaybackResume: this._onPlaybackResume,
      onPlaybackRateChange: this._onPlaybackRateChange,
    });

    return (
@@ -202,6 +234,10 @@ Video.propTypes = {
  onFullscreenPlayerDidPresent: PropTypes.func,
  onFullscreenPlayerWillDismiss: PropTypes.func,
  onFullscreenPlayerDidDismiss: PropTypes.func,
  onReadyForDisplay: PropTypes.func,
  onPlaybackStalled: PropTypes.func,
  onPlaybackResume: PropTypes.func,
  onPlaybackRateChange: PropTypes.func,

  /* Required by react-native */
  scaleX: React.PropTypes.number,