Commit 6988c852 authored by Johannes Lumpe's avatar Johannes Lumpe Committed by Brent Vatne
Browse files

Initial set of changes to make urls work

parent a4c0d46d
Loading
Loading
Loading
Loading
+5 −0
Changes for RCTVideo.h: 5 added lines, 0 removed lines.
Original line number Diff line number Diff line
#import "RCTView.h"

extern NSString *const RNVideoLoadedEvent;
extern NSString *const RNVideoLoadingEvent;
extern NSString *const RNVideoProgressEvent;
extern NSString *const RNVideoLoadingErrorEvent;

@class RCTEventDispatcher;

@interface RCTVideo : UIView
+69 −39
Changes for RCTVideo.m: 69 added lines, 39 removed lines.
Original line number Diff line number Diff line
@@ -5,9 +5,17 @@
#import "UIView+React.h"
#import <AVFoundation/AVFoundation.h>

NSString *const RNVideoLoadedEvent = @"videoLoaded";
NSString *const RNVideoLoadingEvent = @"videoLoading";
NSString *const RNVideoProgressEvent = @"videoProgress";
NSString *const RNVideoLoadingErrorEvent = @"videoLoadError";

static NSString *const statusKeyPath = @"status";

@implementation RCTVideo
{
  AVPlayer *_player;
  AVPlayerItem *_playerItem;
  AVPlayerLayer *_playerLayer;
  NSURL *_videoURL;

@@ -25,8 +33,7 @@
  BOOL _muted;
}

- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher {
  if ((self = [super init])) {
    _eventDispatcher = eventDispatcher;

@@ -39,16 +46,15 @@
  return self;
}

- (void)sendProgressUpdate
{
- (void)sendProgressUpdate {
   AVPlayerItem *video = [_player currentItem];
   if (video == nil) {
   if (video == nil || video.status != AVPlayerItemStatusReadyToPlay) {
     return;
   }

  if (_prevProgressUpdateTime == nil ||
     (([_prevProgressUpdateTime timeIntervalSinceNow] * -1000.0) >= _progressUpdateInterval)) {
    [_eventDispatcher sendInputEventWithName:@"videoProgress" body:@{
    [_eventDispatcher sendInputEventWithName:RNVideoProgressEvent body:@{
      @"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(video.currentTime)],
      @"target": self.reactTag
    }];
@@ -56,17 +62,25 @@
  }
}

- (void)setSrc:(NSString *)source
{
  BOOL isHttpPrefix = [source hasPrefix:@"http://"];
  if (isHttpPrefix) {
    _videoURL = [NSURL URLWithString:source];
  }
  else {
    _videoURL = [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:source ofType:@"mp4"]];
  }
  _player = [AVPlayer playerWithURL:_videoURL];
- (void)setSrc:(NSDictionary *)source {
  bool isNetwork = [source objectForKey:@"isNetwork"];
  NSString *uri = [source objectForKey:@"uri"];
  NSString *type = [source objectForKey:@"type"];

  _videoURL = isNetwork ?
    [NSURL URLWithString:uri] :
    [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]];

  [_playerItem removeObserver:self forKeyPath:statusKeyPath];
  _playerItem = [AVPlayerItem playerItemWithURL:_videoURL];
  [_playerItem addObserver:self forKeyPath:statusKeyPath options:0 context:nil];

  [_player pause];
  [_playerLayer removeFromSuperlayer];

  _player = [AVPlayer playerWithPlayerItem:_playerItem];
  _player.actionAtItemEnd = AVPlayerActionAtItemEndNone;

  _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
  _playerLayer.frame = self.bounds;
  _playerLayer.needsDisplayOnBoundsChange = YES;
@@ -74,28 +88,48 @@
  [self.layer addSublayer:_playerLayer];
  self.layer.needsDisplayOnBoundsChange = YES;

  AVPlayerItem *video = [_player currentItem];
  [_eventDispatcher sendInputEventWithName:RNVideoLoadingEvent body:@{
    @"src": @{
      @"uri":uri,
      @"type": type,
      @"isNetwork":[NSNumber numberWithBool:isNetwork]
    },
    @"target": self.reactTag
  }];
}

  [_eventDispatcher sendInputEventWithName:@"videoLoaded" body:@{
    @"duration": [NSNumber numberWithFloat:CMTimeGetSeconds(video.asset.duration)],
    @"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(video.currentTime)],
    @"canPlayReverse": [NSNumber numberWithBool:video.canPlayReverse],
    @"canPlayFastForward": [NSNumber numberWithBool:video.canPlayFastForward],
    @"canPlaySlowForward": [NSNumber numberWithBool:video.canPlaySlowForward],
    @"canPlaySlowReverse": [NSNumber numberWithBool:video.canPlaySlowReverse],
    @"canStepBackward": [NSNumber numberWithBool:video.canStepBackward],
    @"canStepForward": [NSNumber numberWithBool:video.canStepForward],
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
  if (object == _playerItem) {
    if (_playerItem.status == AVPlayerItemStatusReadyToPlay) {
      [_eventDispatcher sendInputEventWithName:RNVideoLoadedEvent body:@{
        @"duration": [NSNumber numberWithFloat:CMTimeGetSeconds(_playerItem.duration)],
        @"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(_playerItem.currentTime)],
        @"canPlayReverse": [NSNumber numberWithBool:_playerItem.canPlayReverse],
        @"canPlayFastForward": [NSNumber numberWithBool:_playerItem.canPlayFastForward],
        @"canPlaySlowForward": [NSNumber numberWithBool:_playerItem.canPlaySlowForward],
        @"canPlaySlowReverse": [NSNumber numberWithBool:_playerItem.canPlaySlowReverse],
        @"canStepBackward": [NSNumber numberWithBool:_playerItem.canStepBackward],
        @"canStepForward": [NSNumber numberWithBool:_playerItem.canStepForward],
        @"target": self.reactTag
      }];

      [_player play];

  /* rate and volume must be set after play is called */
      [self applyModifiers];
    } else if(_playerItem.status == AVPlayerItemStatusFailed) {
      [_eventDispatcher sendInputEventWithName:RNVideoLoadingErrorEvent body:@{
        @"error": @{
          @"code": [NSNumber numberWithInt:_playerItem.error.code],
          @"domain": _playerItem.error.domain
        },
        @"target": self.reactTag
      }];
    }
  } else {
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
  }
}

- (void)setResizeMode:(NSString*)mode
{
- (void)setResizeMode:(NSString*)mode {
  _playerLayer.videoGravity = mode;
}

@@ -147,7 +181,6 @@
  [self applyModifiers];
}


- (void)setRepeatEnabled {
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(playerItemDidReachEnd:)
@@ -159,8 +192,7 @@
  [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)setRepeat:(BOOL)repeat
{
- (void)setRepeat:(BOOL)repeat {
  if (repeat) {
    [self setRepeatEnabled];
  } else {
@@ -168,20 +200,17 @@
  }
}

- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex
{
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex {
  RCTLogError(@"video cannot have any subviews");
  return;
}

- (void)removeReactSubview:(UIView *)subview
{
- (void)removeReactSubview:(UIView *)subview {
  RCTLogError(@"video cannot have any subviews");
  return;
}

- (void)layoutSubviews
{
- (void)layoutSubviews {
  [super layoutSubviews];
  _playerLayer.frame = self.bounds;
}
@@ -194,6 +223,7 @@
  _player = nil;
  _prevProgressUpdateTime = nil;
  _eventDispatcher = nil;
  [_playerItem removeObserver:self forKeyPath:statusKeyPath];
  [[NSNotificationCenter defaultCenter] removeObserver:self];
}

+9 −3
Changes for RCTVideoManager.m: 9 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -17,16 +17,22 @@
- (NSDictionary *)customDirectEventTypes
{
  return @{
    @"videoLoaded": @{
    RNVideoLoadingEvent: @{
      @"registrationName": @"onLoadStart"
    },
    RNVideoLoadedEvent: @{
      @"registrationName": @"onLoad"
    },
    @"videoProgress": @{
    RNVideoLoadingErrorEvent: @{
      @"registrationName": @"onError"
    },
    RNVideoProgressEvent: @{
      @"registrationName": @"onProgress"
    },
  };
}

RCT_EXPORT_VIEW_PROPERTY(src, NSString);
RCT_EXPORT_VIEW_PROPERTY(src, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(resizeMode, NSString);
RCT_EXPORT_VIEW_PROPERTY(repeat, BOOL);
RCT_EXPORT_VIEW_PROPERTY(paused, BOOL);
+20 −3
Changes for Video.ios.js: 20 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -10,18 +10,21 @@ var VideoStylePropTypes = require('./VideoStylePropTypes');
var NativeMethodsMixin = require('NativeMethodsMixin');
var flattenStyle = require('flattenStyle');
var merge = require('merge');
var deepDiffer = require('deepDiffer');

var Video = React.createClass({
  propTypes: {
    source: PropTypes.string,
    style: StyleSheetPropType(VideoStylePropTypes),
    source: PropTypes.object,
    resizeMode: PropTypes.string,
    repeat: PropTypes.bool,
    paused: PropTypes.bool,
    muted: PropTypes.bool,
    volume: PropTypes.number,
    rate: PropTypes.number,
    onLoadStart: PropTypes.func,
    onLoad: PropTypes.func,
    onError: PropTypes.func,
    onProgress: PropTypes.func,
  },

@@ -32,10 +35,18 @@ var Video = React.createClass({
    validAttributes: ReactIOSViewAttributes.UIView
  },

  _onLoadStart(event) {
    this.props.onLoadStart && this.props.onLoadStart(event.nativeEvent);
  },

  _onLoad(event) {
    this.props.onLoad && this.props.onLoad(event.nativeEvent);
  },

  _onError(event) {
    this.props.onError && this.props.onError(event.nativeEvent);
  },

  _onProgress(event) {
    this.props.onProgress && this.props.onProgress(event.nativeEvent);
  },
@@ -43,6 +54,7 @@ var Video = React.createClass({
  render() {
    var style = flattenStyle([styles.base, this.props.style]);
    var source = this.props.source;
    var isNetwork = !!(source.uri && source.uri.match(/^https?:/));

    var resizeMode;
    if (this.props.resizeMode === VideoResizeMode.stretch) {
@@ -58,9 +70,14 @@ var Video = React.createClass({
    var nativeProps = merge(this.props, {
      style,
      resizeMode: resizeMode,
      src: source,
      src: {
        uri: source.uri,
        isNetwork,
        type: source.type || 'mp4'
      },
      onLoad: this._onLoad,
      onProgress: this._onProgress,

    });

    return <RCTVideo {... nativeProps} />
@@ -69,7 +86,7 @@ var Video = React.createClass({

var RCTVideo = createReactIOSNativeComponentClass({
  validAttributes: merge(ReactIOSViewAttributes.UIView,
    {src: true, resizeMode: true, repeat: true, paused: true, muted: true,
    {src: {diff: deepDiffer}, resizeMode: true, repeat: true, paused: true, muted: true,
     volume: true, rate: true}),
  uiViewClassName: 'RCTVideo',
});