Fix local playback with source dictionary, set default rate/volume
This commit is contained in:
parent
e9e48bb666
commit
bd1dc1f014
68
RCTVideo.m
68
RCTVideo.m
@ -36,6 +36,8 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher {
|
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher {
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
_eventDispatcher = eventDispatcher;
|
_eventDispatcher = eventDispatcher;
|
||||||
|
_rate = 1.0;
|
||||||
|
_volume = 1.0;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -54,7 +56,7 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
@"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(video.currentTime)],
|
@"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(video.currentTime)],
|
||||||
@"target": self.reactTag
|
@"target": self.reactTag
|
||||||
}];
|
}];
|
||||||
|
|
||||||
_prevProgressUpdateTime = [NSDate date];
|
_prevProgressUpdateTime = [NSDate date];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,36 +66,17 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)startProgressTimer {
|
- (void)startProgressTimer {
|
||||||
/* Initialize videoProgress status publisher */
|
|
||||||
_progressUpdateInterval = 250;
|
_progressUpdateInterval = 250;
|
||||||
_prevProgressUpdateTime = nil;
|
_prevProgressUpdateTime = nil;
|
||||||
|
|
||||||
[self stopProgressTimer];
|
[self stopProgressTimer];
|
||||||
|
|
||||||
_progressUpdateTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(sendProgressUpdate)];
|
_progressUpdateTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(sendProgressUpdate)];
|
||||||
[_progressUpdateTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
|
[_progressUpdateTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Player and source
|
#pragma mark - Player and source
|
||||||
|
|
||||||
- (AVPlayerItem*)playerItemForSource:(NSDictionary *)source {
|
|
||||||
bool isNetwork = [source objectForKey:@"isNetwork"];
|
|
||||||
bool isAsset = [source objectForKey:@"isAsset"];
|
|
||||||
NSString *uri = [source objectForKey:@"uri"];
|
|
||||||
NSString *type = [source objectForKey:@"type"];
|
|
||||||
|
|
||||||
NSURL *url = isNetwork || isAsset ?
|
|
||||||
[NSURL URLWithString:uri] :
|
|
||||||
[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]];
|
|
||||||
|
|
||||||
if (isAsset) {
|
|
||||||
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
|
|
||||||
return [AVPlayerItem playerItemWithAsset:asset];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [AVPlayerItem playerItemWithURL:url];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setSrc:(NSDictionary *)source {
|
- (void)setSrc:(NSDictionary *)source {
|
||||||
[_playerItem removeObserver:self forKeyPath:statusKeyPath];
|
[_playerItem removeObserver:self forKeyPath:statusKeyPath];
|
||||||
_playerItem = [self playerItemForSource:source];
|
_playerItem = [self playerItemForSource:source];
|
||||||
@ -122,6 +105,24 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (AVPlayerItem*)playerItemForSource:(NSDictionary *)source {
|
||||||
|
bool isNetwork = [RCTConvert BOOL:[source objectForKey:@"isNetwork"]];
|
||||||
|
bool isAsset = [RCTConvert BOOL:[source objectForKey:@"isAsset"]];
|
||||||
|
NSString *uri = [source objectForKey:@"uri"];
|
||||||
|
NSString *type = [source objectForKey:@"type"];
|
||||||
|
|
||||||
|
NSURL *url = (isNetwork || isAsset) ?
|
||||||
|
[NSURL URLWithString:uri] :
|
||||||
|
[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]];
|
||||||
|
|
||||||
|
if (isAsset) {
|
||||||
|
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
|
||||||
|
return [AVPlayerItem playerItemWithAsset:asset];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [AVPlayerItem playerItemWithURL:url];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
||||||
if (object == _playerItem) {
|
if (object == _playerItem) {
|
||||||
if (_playerItem.status == AVPlayerItemStatusReadyToPlay) {
|
if (_playerItem.status == AVPlayerItemStatusReadyToPlay) {
|
||||||
@ -155,12 +156,13 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)playerItemDidReachEnd:(NSNotification *)notification {
|
- (void)playerItemDidReachEnd:(NSNotification *)notification {
|
||||||
AVPlayerItem *item = [notification object];
|
AVPlayerItem *item = [notification object];
|
||||||
[item seekToTime:kCMTimeZero];
|
[item seekToTime:kCMTimeZero];
|
||||||
[_player play];
|
[_player play];
|
||||||
|
[self applyModifiers];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - additional prop setters
|
#pragma mark - Prop setters
|
||||||
|
|
||||||
- (void)setResizeMode:(NSString*)mode {
|
- (void)setResizeMode:(NSString*)mode {
|
||||||
_playerLayer.videoGravity = mode;
|
_playerLayer.videoGravity = mode;
|
||||||
@ -197,8 +199,7 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
|
|
||||||
- (void)applyModifiers
|
- (void)applyModifiers
|
||||||
{
|
{
|
||||||
/* volume must be set to 0 if muted is YES, or the video seems to
|
/* volume must be set to 0 if muted is YES, or the video freezes playback */
|
||||||
* freeze */
|
|
||||||
if (_muted) {
|
if (_muted) {
|
||||||
[_player setVolume:0];
|
[_player setVolume:0];
|
||||||
[_player setMuted:YES];
|
[_player setMuted:YES];
|
||||||
@ -210,13 +211,6 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
[_player setRate:_rate];
|
[_player setRate:_rate];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)playerItemDidReachEnd:(NSNotification *)notification {
|
|
||||||
AVPlayerItem *item = [notification object];
|
|
||||||
[item seekToTime:kCMTimeZero];
|
|
||||||
[_player play];
|
|
||||||
[self applyModifiers];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setRepeatEnabled {
|
- (void)setRepeatEnabled {
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
selector:@selector(playerItemDidReachEnd:)
|
selector:@selector(playerItemDidReachEnd:)
|
||||||
@ -236,7 +230,7 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - react and view related
|
#pragma mark - React View Management
|
||||||
|
|
||||||
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex {
|
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex {
|
||||||
RCTLogError(@"video cannot have any subviews");
|
RCTLogError(@"video cannot have any subviews");
|
||||||
@ -253,7 +247,7 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
_playerLayer.frame = self.bounds;
|
_playerLayer.frame = self.bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - lifecycle
|
#pragma mark - Lifecycle
|
||||||
|
|
||||||
- (void)removeFromSuperview
|
- (void)removeFromSuperview
|
||||||
{
|
{
|
||||||
|
@ -90,8 +90,8 @@ var Video = React.createClass({
|
|||||||
|
|
||||||
var RCTVideo = createReactIOSNativeComponentClass({
|
var RCTVideo = createReactIOSNativeComponentClass({
|
||||||
validAttributes: merge(ReactIOSViewAttributes.UIView,
|
validAttributes: merge(ReactIOSViewAttributes.UIView,
|
||||||
{src: {diff: deepDiffer}, resizeMode: true, repeat: true, paused: true, muted: true,
|
{src: {diff: deepDiffer}, resizeMode: true, repeat: true,
|
||||||
volume: true, rate: true}),
|
paused: true, muted: true, volume: true, rate: true}),
|
||||||
uiViewClassName: 'RCTVideo',
|
uiViewClassName: 'RCTVideo',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user