Initial commit for seeking
This commit is contained in:
parent
ac3e4cf773
commit
45d79b701e
@ -3,6 +3,7 @@
|
|||||||
extern NSString *const RNVideoEventLoaded;
|
extern NSString *const RNVideoEventLoaded;
|
||||||
extern NSString *const RNVideoEventLoading;
|
extern NSString *const RNVideoEventLoading;
|
||||||
extern NSString *const RNVideoEventProgress;
|
extern NSString *const RNVideoEventProgress;
|
||||||
|
extern NSString *const RNVideoEventSeek;
|
||||||
extern NSString *const RNVideoEventLoadingError;
|
extern NSString *const RNVideoEventLoadingError;
|
||||||
|
|
||||||
@class RCTEventDispatcher;
|
@class RCTEventDispatcher;
|
||||||
|
63
RCTVideo.m
63
RCTVideo.m
@ -9,6 +9,7 @@
|
|||||||
NSString *const RNVideoEventLoaded = @"videoLoaded";
|
NSString *const RNVideoEventLoaded = @"videoLoaded";
|
||||||
NSString *const RNVideoEventLoading = @"videoLoading";
|
NSString *const RNVideoEventLoading = @"videoLoading";
|
||||||
NSString *const RNVideoEventProgress = @"videoProgress";
|
NSString *const RNVideoEventProgress = @"videoProgress";
|
||||||
|
NSString *const RNVideoEventSeek = @"videoSeek";
|
||||||
NSString *const RNVideoEventLoadingError = @"videoLoadError";
|
NSString *const RNVideoEventLoadingError = @"videoLoadError";
|
||||||
|
|
||||||
static NSString *const statusKeyPath = @"status";
|
static NSString *const statusKeyPath = @"status";
|
||||||
@ -23,6 +24,10 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
/* Required to publish events */
|
/* Required to publish events */
|
||||||
RCTEventDispatcher *_eventDispatcher;
|
RCTEventDispatcher *_eventDispatcher;
|
||||||
|
|
||||||
|
bool _pendingSeek;
|
||||||
|
float _pendingSeekTime;
|
||||||
|
float _lastSeekTime;
|
||||||
|
|
||||||
/* For sending videoProgress events */
|
/* For sending videoProgress events */
|
||||||
id _progressUpdateTimer;
|
id _progressUpdateTimer;
|
||||||
int _progressUpdateInterval;
|
int _progressUpdateInterval;
|
||||||
@ -39,6 +44,10 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
_eventDispatcher = eventDispatcher;
|
_eventDispatcher = eventDispatcher;
|
||||||
_rate = 1.0;
|
_rate = 1.0;
|
||||||
_volume = 1.0;
|
_volume = 1.0;
|
||||||
|
|
||||||
|
_pendingSeek = false;
|
||||||
|
_pendingSeekTime = 0.0f;
|
||||||
|
_lastSeekTime = 0.0f;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -169,8 +178,7 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
_playerLayer.videoGravity = mode;
|
_playerLayer.videoGravity = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setPaused:(BOOL)paused
|
- (void)setPaused:(BOOL)paused {
|
||||||
{
|
|
||||||
if (paused) {
|
if (paused) {
|
||||||
[self stopProgressTimer];
|
[self stopProgressTimer];
|
||||||
[_player pause];
|
[_player pause];
|
||||||
@ -181,14 +189,54 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setRate:(float)rate
|
- (void)setSeek:(NSDictionary*)seek {
|
||||||
{
|
NSNumber *seekValue = [seek objectForKey:@"time"];
|
||||||
|
if (!seekValue) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int timeScale = 10000;
|
||||||
|
float seekTime = [RCTConvert float:seekValue];
|
||||||
|
bool force = [RCTConvert BOOL:[seek objectForKey:@"force"]];
|
||||||
|
|
||||||
|
if (seekTime == _lastSeekTime && !force) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVPlayerItem *item = _player.currentItem;
|
||||||
|
if (item && item.status == AVPlayerItemStatusReadyToPlay) {
|
||||||
|
// TODO check loadedTimeRanges
|
||||||
|
|
||||||
|
CMTime cmSeekTime = CMTimeMakeWithSeconds(seekTime, timeScale);
|
||||||
|
CMTime current = item.currentTime;
|
||||||
|
// TODO figure out a good tolerance level
|
||||||
|
CMTime tolerance = CMTimeMake(1000, timeScale);
|
||||||
|
|
||||||
|
if (CMTimeCompare(current, cmSeekTime) != 0) {
|
||||||
|
[_player seekToTime:cmSeekTime toleranceBefore:tolerance toleranceAfter:tolerance];
|
||||||
|
_pendingSeek = false;
|
||||||
|
_lastSeekTime = seekTime;
|
||||||
|
[_eventDispatcher sendInputEventWithName:RNVideoEventSeek body:@{
|
||||||
|
@"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(item.currentTime)],
|
||||||
|
@"seekTime": seekValue,
|
||||||
|
@"target": self.reactTag
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// TODO see if this makes sense and if so,
|
||||||
|
// actually implement it
|
||||||
|
_pendingSeek = true;
|
||||||
|
_pendingSeekTime = seekTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setRate:(float)rate {
|
||||||
_rate = rate;
|
_rate = rate;
|
||||||
[self applyModifiers];
|
[self applyModifiers];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setMuted:(BOOL)muted
|
- (void)setMuted:(BOOL)muted {
|
||||||
{
|
|
||||||
_muted = muted;
|
_muted = muted;
|
||||||
[self applyModifiers];
|
[self applyModifiers];
|
||||||
}
|
}
|
||||||
@ -198,8 +246,7 @@ static NSString *const statusKeyPath = @"status";
|
|||||||
[self applyModifiers];
|
[self applyModifiers];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applyModifiers
|
- (void)applyModifiers {
|
||||||
{
|
|
||||||
/* volume must be set to 0 if muted is YES, or the video freezes playback */
|
/* volume must be set to 0 if muted is YES, or the video freezes playback */
|
||||||
if (_muted) {
|
if (_muted) {
|
||||||
[_player setVolume:0];
|
[_player setVolume:0];
|
||||||
|
@ -29,6 +29,9 @@
|
|||||||
RNVideoEventProgress: @{
|
RNVideoEventProgress: @{
|
||||||
@"registrationName": @"onProgress"
|
@"registrationName": @"onProgress"
|
||||||
},
|
},
|
||||||
|
RNVideoEventSeek: @{
|
||||||
|
@"registrationName": @"onSeek"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +42,7 @@ RCT_EXPORT_VIEW_PROPERTY(paused, BOOL);
|
|||||||
RCT_EXPORT_VIEW_PROPERTY(muted, BOOL);
|
RCT_EXPORT_VIEW_PROPERTY(muted, BOOL);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(volume, float);
|
RCT_EXPORT_VIEW_PROPERTY(volume, float);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(rate, float);
|
RCT_EXPORT_VIEW_PROPERTY(rate, float);
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(seek, NSDictionary);
|
||||||
|
|
||||||
- (NSDictionary *)constantsToExport
|
- (NSDictionary *)constantsToExport
|
||||||
{
|
{
|
||||||
|
12
Video.ios.js
12
Video.ios.js
@ -21,6 +21,7 @@ var Video = React.createClass({
|
|||||||
resizeMode: PropTypes.string,
|
resizeMode: PropTypes.string,
|
||||||
repeat: PropTypes.bool,
|
repeat: PropTypes.bool,
|
||||||
paused: PropTypes.bool,
|
paused: PropTypes.bool,
|
||||||
|
seek: PropTypes.number,
|
||||||
muted: PropTypes.bool,
|
muted: PropTypes.bool,
|
||||||
volume: PropTypes.number,
|
volume: PropTypes.number,
|
||||||
rate: PropTypes.number,
|
rate: PropTypes.number,
|
||||||
@ -53,6 +54,10 @@ var Video = React.createClass({
|
|||||||
this.props.onProgress && this.props.onProgress(event.nativeEvent);
|
this.props.onProgress && this.props.onProgress(event.nativeEvent);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onSeek(event) {
|
||||||
|
this.props.onSeek && this.props.onSeek(event.nativeEvent);
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var style = flattenStyle([styles.base, this.props.style]);
|
var style = flattenStyle([styles.base, this.props.style]);
|
||||||
var source = this.props.source;
|
var source = this.props.source;
|
||||||
@ -71,6 +76,10 @@ var Video = React.createClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
var nativeProps = merge(this.props, {
|
var nativeProps = merge(this.props, {
|
||||||
|
seek: {
|
||||||
|
time: this.props.seek,
|
||||||
|
force: this.props.forceSeek
|
||||||
|
},
|
||||||
style,
|
style,
|
||||||
resizeMode: resizeMode,
|
resizeMode: resizeMode,
|
||||||
src: {
|
src: {
|
||||||
@ -81,7 +90,6 @@ var Video = React.createClass({
|
|||||||
},
|
},
|
||||||
onLoad: this._onLoad,
|
onLoad: this._onLoad,
|
||||||
onProgress: this._onProgress,
|
onProgress: this._onProgress,
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return <RCTVideo {... nativeProps} />
|
return <RCTVideo {... nativeProps} />
|
||||||
@ -91,7 +99,7 @@ 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,
|
{src: {diff: deepDiffer}, resizeMode: true, repeat: true,
|
||||||
paused: true, muted: true, volume: true, rate: true}),
|
seek: {diff: () => true}, paused: true, muted: true, volume: true, rate: true}),
|
||||||
uiViewClassName: 'RCTVideo',
|
uiViewClassName: 'RCTVideo',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user