From f2b0dbd2db81f2e03f2cee457eb4e465ec111b76 Mon Sep 17 00:00:00 2001 From: Bernd Paradies Date: Tue, 22 Dec 2015 17:39:04 -0600 Subject: [PATCH] Introducing custom/native/embed skins --- Examples/VideoPlayer/.gitignore | 2 + .../contents.xcworkspacedata | 7 - .../xcshareddata/VideoPlayer.xccheckout | 41 --- .../UserInterfaceState.xcuserstate | Bin 31267 -> 0 bytes .../xcschemes/VideoPlayer.xcscheme | 88 ------ .../xcdebugger/Breakpoints_v2.xcbkptlist | 21 -- .../xcschemes/xcschememanagement.plist | 22 -- Examples/VideoPlayer/index.ios.js | 103 ++++++- .../RCTVideo.xcodeproj/project.pbxproj | 260 ------------------ Examples/VideoPlayer/package.json | 5 +- RCTVideo.h | 4 + RCTVideo.m | 246 +++++++++++++---- RCTVideo.xcodeproj/project.pbxproj | 2 - RCTVideoManager.m | 2 + Video.js | 6 +- package.json | 3 +- 16 files changed, 299 insertions(+), 513 deletions(-) delete mode 100644 Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcshareddata/VideoPlayer.xccheckout delete mode 100644 Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcuserdata/brentvatne.xcuserdatad/UserInterfaceState.xcuserstate delete mode 100644 Examples/VideoPlayer/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme delete mode 100644 Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist delete mode 100644 Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/project.pbxproj diff --git a/Examples/VideoPlayer/.gitignore b/Examples/VideoPlayer/.gitignore index 07e4fe72..52594ec7 100644 --- a/Examples/VideoPlayer/.gitignore +++ b/Examples/VideoPlayer/.gitignore @@ -1 +1,3 @@ node_modules/**/* +VideoPlayer.xcodeproj/project.xcworkspace/**/* +VideoPlayer.xcodeproj/xcuserdata/**/* \ No newline at end of file diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 4ac4c91f..00000000 --- a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcshareddata/VideoPlayer.xccheckout b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcshareddata/VideoPlayer.xccheckout deleted file mode 100644 index 6ce4fd2f..00000000 --- a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcshareddata/VideoPlayer.xccheckout +++ /dev/null @@ -1,41 +0,0 @@ - - - - - IDESourceControlProjectFavoriteDictionaryKey - - IDESourceControlProjectIdentifier - 9B1B824B-5918-47F5-B27A-FA559B781ACC - IDESourceControlProjectName - VideoPlayer - IDESourceControlProjectOriginsDictionary - - D05F265D0E65FFE673B2E9F5A4680A7F46E27F31 - github.com:johanneslumpe/react-native-video.git - - IDESourceControlProjectPath - Examples/VideoPlayer/VideoPlayer.xcodeproj - IDESourceControlProjectRelativeInstallPathDictionary - - D05F265D0E65FFE673B2E9F5A4680A7F46E27F31 - ../../../.. - - IDESourceControlProjectURL - github.com:johanneslumpe/react-native-video.git - IDESourceControlProjectVersion - 111 - IDESourceControlProjectWCCIdentifier - D05F265D0E65FFE673B2E9F5A4680A7F46E27F31 - IDESourceControlProjectWCConfigurations - - - IDESourceControlRepositoryExtensionIdentifierKey - public.vcs.git - IDESourceControlWCCIdentifierKey - D05F265D0E65FFE673B2E9F5A4680A7F46E27F31 - IDESourceControlWCCName - react-native-video - - - - diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcuserdata/brentvatne.xcuserdatad/UserInterfaceState.xcuserstate b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcuserdata/brentvatne.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index 01791feea31954459161f669bc917a5e721defa1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31267 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 I|BvhWe-~^o5&!@I diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme deleted file mode 100644 index b089e027..00000000 --- a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist deleted file mode 100644 index b1a4c519..00000000 --- a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index bc98ef59..00000000 --- a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - SchemeUserState - - VideoPlayer.xcscheme_^#shared#^_ - - orderHint - 0 - - - SuppressBuildableAutocreation - - 13B07F861A680F5B00A75B9A - - primary - - - - - diff --git a/Examples/VideoPlayer/index.ios.js b/Examples/VideoPlayer/index.ios.js index c77f53d5..3e97d984 100644 --- a/Examples/VideoPlayer/index.ios.js +++ b/Examples/VideoPlayer/index.ios.js @@ -21,6 +21,9 @@ var VideoPlayer = React.createClass({ resizeMode: 'contain', duration: 0.0, currentTime: 0.0, + controls: false, + paused: true, + skin: 'custom' } }, @@ -40,6 +43,21 @@ var VideoPlayer = React.createClass({ } }, + renderSkinControl(skin) { + var isSelected = this.state.skin == skin; + var selectControls = skin == 'native' || skin == 'embed'; + return ( + { this.setState({ + controls: selectControls, + skin: skin + }) }}> + + {skin} + + + ); + }, + renderRateControl(rate) { var isSelected = (this.state.rate == rate); @@ -76,7 +94,7 @@ var VideoPlayer = React.createClass({ ) }, - render() { + renderCustomSkin() { var flexCompleted = this.getCurrentTimePercentage() * 100; var flexRemaining = (1 - this.getCurrentTimePercentage()) * 100; @@ -97,12 +115,17 @@ var VideoPlayer = React.createClass({ + + + {this.renderSkinControl('custom')} + {this.renderSkinControl('native')} + {this.renderSkinControl('embed')} + + - {this.renderRateControl(0.25)} {this.renderRateControl(0.5)} {this.renderRateControl(1.0)} - {this.renderRateControl(1.5)} {this.renderRateControl(2.0)} @@ -128,7 +151,63 @@ var VideoPlayer = React.createClass({ ); + }, + + renderNativeSkin() { + var videoStyle = this.state.skin == 'embed' ? styles.nativeVideoControls : styles.fullScreen; + return ( + + + + + + + {this.renderSkinControl('custom')} + {this.renderSkinControl('native')} + {this.renderSkinControl('embed')} + + + + + {this.renderRateControl(0.5)} + {this.renderRateControl(1.0)} + {this.renderRateControl(2.0)} + + + + {this.renderVolumeControl(0.5)} + {this.renderVolumeControl(1)} + {this.renderVolumeControl(1.5)} + + + + {this.renderResizeModeControl('cover')} + {this.renderResizeModeControl('contain')} + {this.renderResizeModeControl('stretch')} + + + + + + ); + }, + + render() { + return this.state.controls ? this.renderNativeSkin() : this.renderCustomSkin(); } + }); @@ -150,9 +229,9 @@ var styles = StyleSheet.create({ backgroundColor: "transparent", borderRadius: 5, position: 'absolute', - bottom: 20, - left: 20, - right: 20, + bottom: 44, + left: 4, + right: 4, }, progress: { flex: 1, @@ -171,10 +250,14 @@ var styles = StyleSheet.create({ generalControls: { flex: 1, flexDirection: 'row', - borderRadius: 4, overflow: 'hidden', paddingBottom: 10, }, + skinControl: { + flex: 1, + flexDirection: 'row', + justifyContent: 'center', + }, rateControl: { flex: 1, flexDirection: 'row', @@ -189,7 +272,7 @@ var styles = StyleSheet.create({ flex: 1, flexDirection: 'row', alignItems: 'center', - justifyContent: 'center', + justifyContent: 'center' }, controlOption: { alignSelf: 'center', @@ -199,6 +282,10 @@ var styles = StyleSheet.create({ paddingRight: 2, lineHeight: 12, }, + nativeVideoControls: { + top: 184, + height: 300 + } }); AppRegistry.registerComponent('VideoPlayer', () => VideoPlayer); diff --git a/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/project.pbxproj b/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/project.pbxproj deleted file mode 100644 index e6ddaaf1..00000000 --- a/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/project.pbxproj +++ /dev/null @@ -1,260 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - BBD49E3F1AC8DEF000610F8E /* RCTVideo.m in Sources */ = {isa = PBXBuildFile; fileRef = BBD49E3A1AC8DEF000610F8E /* RCTVideo.m */; }; - BBD49E401AC8DEF000610F8E /* RCTVideoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BBD49E3C1AC8DEF000610F8E /* RCTVideoManager.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 58B511D91A9E6C8500147676 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "include/$(PRODUCT_NAME)"; - dstSubfolderSpec = 16; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 134814201AA4EA6300B7C361 /* libRCTVideo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTVideo.a; sourceTree = BUILT_PRODUCTS_DIR; }; - BBD49E391AC8DEF000610F8E /* RCTVideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTVideo.h; sourceTree = ""; }; - BBD49E3A1AC8DEF000610F8E /* RCTVideo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTVideo.m; sourceTree = ""; }; - BBD49E3B1AC8DEF000610F8E /* RCTVideoManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTVideoManager.h; sourceTree = ""; }; - BBD49E3C1AC8DEF000610F8E /* RCTVideoManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTVideoManager.m; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 58B511D81A9E6C8500147676 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 134814211AA4EA7D00B7C361 /* Products */ = { - isa = PBXGroup; - children = ( - 134814201AA4EA6300B7C361 /* libRCTVideo.a */, - ); - name = Products; - sourceTree = ""; - }; - 58B511D21A9E6C8500147676 = { - isa = PBXGroup; - children = ( - BBD49E391AC8DEF000610F8E /* RCTVideo.h */, - BBD49E3A1AC8DEF000610F8E /* RCTVideo.m */, - BBD49E3B1AC8DEF000610F8E /* RCTVideoManager.h */, - BBD49E3C1AC8DEF000610F8E /* RCTVideoManager.m */, - 134814211AA4EA7D00B7C361 /* Products */, - ); - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 58B511DA1A9E6C8500147676 /* RCTVideo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTVideo" */; - buildPhases = ( - 58B511D71A9E6C8500147676 /* Sources */, - 58B511D81A9E6C8500147676 /* Frameworks */, - 58B511D91A9E6C8500147676 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = RCTVideo; - productName = RCTDataManager; - productReference = 134814201AA4EA6300B7C361 /* libRCTVideo.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 58B511D31A9E6C8500147676 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; - TargetAttributes = { - 58B511DA1A9E6C8500147676 = { - CreatedOnToolsVersion = 6.1.1; - }; - }; - }; - buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTVideo" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 58B511D21A9E6C8500147676; - productRefGroup = 58B511D21A9E6C8500147676; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 58B511DA1A9E6C8500147676 /* RCTVideo */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 58B511D71A9E6C8500147676 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BBD49E3F1AC8DEF000610F8E /* RCTVideo.m in Sources */, - BBD49E401AC8DEF000610F8E /* RCTVideoManager.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 58B511ED1A9E6C8500147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 58B511EE1A9E6C8500147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 58B511F01A9E6C8500147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../React/**", - "$(SRCROOT)/../react-native/React/**", - "$(SRCROOT)/node_modules/react-native/React/**", - ); - LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RCTVideo; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 58B511F11A9E6C8500147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../React/**", - "$(SRCROOT)/../react-native/React/**", - "$(SRCROOT)/node_modules/react-native/React/**", - ); - LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RCTVideo; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTVideo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B511ED1A9E6C8500147676 /* Debug */, - 58B511EE1A9E6C8500147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTVideo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B511F01A9E6C8500147676 /* Debug */, - 58B511F11A9E6C8500147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 58B511D31A9E6C8500147676 /* Project object */; -} diff --git a/Examples/VideoPlayer/package.json b/Examples/VideoPlayer/package.json index 2d097498..6be7c953 100644 --- a/Examples/VideoPlayer/package.json +++ b/Examples/VideoPlayer/package.json @@ -5,8 +5,11 @@ "scripts": { "start": "node_modules/react-native/packager/packager.sh" }, + "scripts": { + "postinstall" : "cp ../../*.js ../../*.m ../../*.h ../../README.md ../../package.json ./node_modules/react-native-video && cp ../../RCTVideo.xcodeproj/project.pbxproj ./node_modules/react-native-video/RCTVideo.xcodeproj/project.pbxproj" + }, "dependencies": { "react-native": "^0.16.0", - "react-native-video": "brentvatne/react-native-video#feature/android-support" + "react-native-video": "brentvatne/react-native-video" } } diff --git a/RCTVideo.h b/RCTVideo.h index 1fc82e43..757ed542 100644 --- a/RCTVideo.h +++ b/RCTVideo.h @@ -1,4 +1,6 @@ #import "RCTView.h" +#import +#import "AVKit/AVKit.h" @class RCTEventDispatcher; @@ -6,4 +8,6 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER; +- (AVPlayerViewController*)createPlayerViewController:(AVPlayer*)player withPlayerItem:(AVPlayerItem*)playerItem; + @end diff --git a/RCTVideo.m b/RCTVideo.m index 37e09e8b..68199f72 100644 --- a/RCTVideo.m +++ b/RCTVideo.m @@ -3,7 +3,6 @@ #import "RCTBridgeModule.h" #import "RCTEventDispatcher.h" #import "UIView+React.h" -#import static NSString *const statusKeyPath = @"status"; static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"; @@ -14,6 +13,7 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" AVPlayerItem *_playerItem; BOOL _playerItemObserversSet; AVPlayerLayer *_playerLayer; + AVPlayerViewController *_playerViewController; NSURL *_videoURL; /* Required to publish events */ @@ -24,9 +24,9 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" float _lastSeekTime; /* For sending videoProgress events */ - id _progressUpdateTimer; - int _progressUpdateInterval; - NSDate *_prevProgressUpdateTime; + Float64 _progressUpdateInterval; + BOOL _controls; + id _timeObserver; /* Keep track of any modifiers, need to be applied after each play */ float _volume; @@ -48,6 +48,8 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" _pendingSeek = false; _pendingSeekTime = 0.0f; _lastSeekTime = 0.0f; + _progressUpdateInterval = 250; + _controls = NO; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) @@ -63,6 +65,42 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" return self; } +- (AVPlayerViewController*)createPlayerViewController:(AVPlayer*)player withPlayerItem:(AVPlayerItem*)playerItem { + AVPlayerViewController* playerLayer= [[AVPlayerViewController alloc] init]; + playerLayer.view.frame = self.bounds; + playerLayer.player = _player; + playerLayer.view.frame = self.bounds; + return playerLayer; +} + +/* --------------------------------------------------------- + ** Get the duration for a AVPlayerItem. + ** ------------------------------------------------------- */ + +- (CMTime)playerItemDuration +{ + AVPlayerItem *playerItem = [_player currentItem]; + if (playerItem.status == AVPlayerItemStatusReadyToPlay) + { + return([playerItem duration]); + } + + return(kCMTimeInvalid); +} + + +/* Cancels the previously registered time observer. */ +-(void)removePlayerTimeObserver +{ + if (_timeObserver) + { + [_player removeTimeObserver:_timeObserver]; + _timeObserver = nil; + } +} + +#pragma mark - Progress + - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -73,14 +111,13 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" - (void)applicationWillResignActive:(NSNotification *)notification { if (!_paused) { - [self stopProgressTimer]; + [_player pause]; [_player setRate:0.0]; } } - (void)applicationWillEnterForeground:(NSNotification *)notification { - [self startProgressTimer]; [self applyModifiers]; } @@ -88,18 +125,29 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" - (void)sendProgressUpdate { - AVPlayerItem *video = [_player currentItem]; - if (video == nil || video.status != AVPlayerItemStatusReadyToPlay) { - return; - } + AVPlayerItem *video = [_player currentItem]; + if (video == nil || video.status != AVPlayerItemStatusReadyToPlay) { + return; + } + + CMTime playerDuration = [self playerItemDuration]; + if (CMTIME_IS_INVALID(playerDuration)) { + return; + } - if (_prevProgressUpdateTime == nil || (([_prevProgressUpdateTime timeIntervalSinceNow] * -1000.0) >= _progressUpdateInterval)) { - [_eventDispatcher sendInputEventWithName:@"onVideoProgress" - body:@{@"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(video.currentTime)], - @"playableDuration": [self calculatePlayableDuration], - @"target": self.reactTag}]; - _prevProgressUpdateTime = [NSDate date]; - } + CMTime currentTime = _player.currentTime; + const Float64 duration = CMTimeGetSeconds(playerDuration); + const Float64 currentTimeSecs = CMTimeGetSeconds(currentTime); + if( currentTimeSecs >= 0 && currentTimeSecs <= duration) { + [_eventDispatcher sendInputEventWithName:@"onVideoProgress" + body:@{ + @"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(currentTime)], + @"playableDuration": [self calculatePlayableDuration], + @"atValue": [NSNumber numberWithLongLong:currentTime.value], + @"atTimescale": [NSNumber numberWithInt:currentTime.timescale], + @"target": self.reactTag + }]; + } } /*! @@ -127,22 +175,6 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" return [NSNumber numberWithInteger:0]; } -- (void)stopProgressTimer -{ - [_progressUpdateTimer invalidate]; -} - -- (void)startProgressTimer -{ - _progressUpdateInterval = 250; - _prevProgressUpdateTime = nil; - - [self stopProgressTimer]; - - _progressUpdateTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(sendProgressUpdate)]; - [_progressUpdateTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; -} - - (void)addPlayerItemObservers { [_playerItem addObserver:self forKeyPath:statusKeyPath options:0 context:nil]; @@ -166,25 +198,27 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" - (void)setSrc:(NSDictionary *)source { + [self removePlayerTimeObserver]; [self removePlayerItemObservers]; _playerItem = [self playerItemForSource:source]; [self addPlayerItemObservers]; [_player pause]; [_playerLayer removeFromSuperlayer]; + _playerLayer = nil; + [_playerViewController.view removeFromSuperview]; + _playerViewController = nil; _player = [AVPlayer playerWithPlayerItem:_playerItem]; _player.actionAtItemEnd = AVPlayerActionAtItemEndNone; - _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player]; - _playerLayer.frame = self.bounds; - _playerLayer.needsDisplayOnBoundsChange = YES; - - [self applyModifiers]; - - [self.layer addSublayer:_playerLayer]; - self.layer.needsDisplayOnBoundsChange = YES; - + const Float64 progressUpdateIntervalMS = _progressUpdateInterval / 1000; + // @see endScrubbing in AVPlayerDemoPlaybackViewController.m of https://developer.apple.com/library/ios/samplecode/AVPlayerDemo/Introduction/Intro.html + __weak RCTVideo *weakSelf = self; + _timeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(progressUpdateIntervalMS, NSEC_PER_SEC) + queue:NULL + usingBlock:^(CMTime time) { [weakSelf sendProgressUpdate]; } + ]; [_eventDispatcher sendInputEventWithName:@"onVideoLoadStart" body:@{@"src": @{ @"uri": [source objectForKey:@"uri"], @@ -214,7 +248,7 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - if (object == _playerItem) { + if (object == _playerItem) { if ([keyPath isEqualToString:statusKeyPath]) { // Handle player item status change. @@ -236,7 +270,6 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" @"canStepForward": [NSNumber numberWithBool:_playerItem.canStepForward], @"target": self.reactTag}]; - [self startProgressTimer]; [self attachListeners]; [self applyModifiers]; } else if(_playerItem.status == AVPlayerItemStatusFailed) { @@ -253,7 +286,7 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" } } } else { - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } @@ -281,23 +314,40 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" - (void)setResizeMode:(NSString*)mode { + if( _controls ) + { + _playerViewController.videoGravity = mode; + } + else + { + _playerLayer.videoGravity = mode; + } _resizeMode = mode; - _playerLayer.videoGravity = mode; } - (void)setPaused:(BOOL)paused { if (paused) { - [self stopProgressTimer]; + [_player pause]; [_player setRate:0.0]; } else { - [self startProgressTimer]; + [_player play]; [_player setRate:_rate]; } - + _paused = paused; } +- (float)getCurrentTime +{ + return _playerItem != NULL ? CMTimeGetSeconds(_playerItem.currentTime) : 0; +} + +- (void)setCurrentTime:(float)currentTime +{ + [self setSeek: currentTime]; +} + - (void)setSeek:(float)seekTime { int timeScale = 10000; @@ -310,7 +360,7 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" 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 completionHandler:^(BOOL finished) { [_eventDispatcher sendInputEventWithName:@"onVideoSeek" @@ -360,48 +410,126 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp" [self setResizeMode:_resizeMode]; [self setRepeat:_repeat]; [self setPaused:_paused]; + [self setControls:_controls]; } - (void)setRepeat:(BOOL)repeat { _repeat = repeat; } +- (void)usePlayerViewController +{ + if( _player ) + { + _playerViewController = [self createPlayerViewController:_player withPlayerItem:_playerItem]; + [self addSubview:_playerViewController.view]; + } +} + +- (void)usePlayerLayer +{ + if( _player ) + { + _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player]; + _playerLayer.frame = self.bounds; + _playerLayer.needsDisplayOnBoundsChange = YES; + + [self.layer addSublayer:_playerLayer]; + self.layer.needsDisplayOnBoundsChange = YES; + } +} + +- (void)setControls:(BOOL)controls +{ + if( _controls != controls || (!_playerLayer && !_playerViewController) ) + { + _controls = controls; + if( _controls ) + { + [_playerLayer removeFromSuperlayer]; + _playerLayer = nil; + [self usePlayerViewController]; + } + else + { + [_playerViewController.view removeFromSuperview]; + _playerViewController = nil; + [self usePlayerLayer]; + } + } +} + #pragma mark - React View Management - (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex { - RCTLogError(@"video cannot have any subviews"); + // We are early in the game and somebody wants to set a subview. + // That can only be in the context of playerViewController. + if( !_controls && !_playerLayer && !_playerViewController ) + { + [self setControls:true]; + } + + if( _controls ) + { + view.frame = self.bounds; + [_playerViewController.contentOverlayView insertSubview:view atIndex:atIndex]; + } + else + { + RCTLogError(@"video cannot have any subviews"); + } return; } - (void)removeReactSubview:(UIView *)subview { - RCTLogError(@"video cannot have any subviews"); + if( _controls ) + { + [subview removeFromSuperview]; + } + else + { + RCTLogError(@"video cannot have any subviews"); + } return; } - (void)layoutSubviews { [super layoutSubviews]; - [CATransaction begin]; - [CATransaction setAnimationDuration:0]; - _playerLayer.frame = self.bounds; - [CATransaction commit]; + if( _controls ) + { + _playerViewController.view.frame = self.bounds; + + // also adjust all subviews of contentOverlayView + for (UIView* subview in _playerViewController.contentOverlayView.subviews) { + subview.frame = self.bounds; + } + } + else + { + [CATransaction begin]; + [CATransaction setAnimationDuration:0]; + _playerLayer.frame = self.bounds; + [CATransaction commit]; + } } #pragma mark - Lifecycle - (void)removeFromSuperview { - [_progressUpdateTimer invalidate]; - _prevProgressUpdateTime = nil; - [_player pause]; _player = nil; [_playerLayer removeFromSuperlayer]; _playerLayer = nil; + + [_playerViewController.view removeFromSuperview]; + _playerViewController = nil; + [self removePlayerTimeObserver]; [self removePlayerItemObservers]; _eventDispatcher = nil; diff --git a/RCTVideo.xcodeproj/project.pbxproj b/RCTVideo.xcodeproj/project.pbxproj index e6ddaaf1..8eda4458 100644 --- a/RCTVideo.xcodeproj/project.pbxproj +++ b/RCTVideo.xcodeproj/project.pbxproj @@ -205,7 +205,6 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../React/**", "$(SRCROOT)/../react-native/React/**", "$(SRCROOT)/node_modules/react-native/React/**", ); @@ -222,7 +221,6 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../React/**", "$(SRCROOT)/../react-native/React/**", "$(SRCROOT)/node_modules/react-native/React/**", ); diff --git a/RCTVideoManager.m b/RCTVideoManager.m index 3f931999..7c0dfbc2 100644 --- a/RCTVideoManager.m +++ b/RCTVideoManager.m @@ -38,9 +38,11 @@ RCT_EXPORT_VIEW_PROPERTY(resizeMode, NSString); RCT_EXPORT_VIEW_PROPERTY(repeat, BOOL); RCT_EXPORT_VIEW_PROPERTY(paused, BOOL); RCT_EXPORT_VIEW_PROPERTY(muted, BOOL); +RCT_EXPORT_VIEW_PROPERTY(controls, BOOL); RCT_EXPORT_VIEW_PROPERTY(volume, float); RCT_EXPORT_VIEW_PROPERTY(rate, float); RCT_EXPORT_VIEW_PROPERTY(seek, float); +RCT_EXPORT_VIEW_PROPERTY(currentTime, float); - (NSDictionary *)constantsToExport { diff --git a/Video.js b/Video.js index 77323549..67978988 100644 --- a/Video.js +++ b/Video.js @@ -127,13 +127,15 @@ Video.propTypes = { muted: PropTypes.bool, volume: PropTypes.number, rate: PropTypes.number, + controls: PropTypes.bool, + currentTime: PropTypes.number, onLoadStart: PropTypes.func, onLoad: PropTypes.func, onError: PropTypes.func, onProgress: PropTypes.func, onSeek: PropTypes.func, onEnd: PropTypes.func, - + /* Required by react-native */ scaleX: React.PropTypes.number, scaleY: React.PropTypes.number, @@ -146,7 +148,7 @@ Video.propTypes = { const RCTVideo = requireNativeComponent('RCTVideo', Video, { nativeOnly: { src: true, - seek: true, + seek: true }, }); diff --git a/package.json b/package.json index 8dd18d0a..c9592151 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,7 @@ "RCTVideoManager.m", "README.md", "Video.js", - "VideoResizeMode.js", - "VideoStylePropTypes.js" + "VideoResizeMode.js" ], "contributors": [ {