diff --git a/Examples/VideoPlayer/.gitignore b/Examples/VideoPlayer/.gitignore new file mode 100644 index 00000000..07e4fe72 --- /dev/null +++ b/Examples/VideoPlayer/.gitignore @@ -0,0 +1 @@ +node_modules/**/* diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.pbxproj b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.pbxproj new file mode 100644 index 00000000..131b4cd6 --- /dev/null +++ b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.pbxproj @@ -0,0 +1,622 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 00481BE81AC0C86700671115 /* libRCTWebSocketDebugger.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */; }; + 00481BEA1AC0C89D00671115 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 00481BE91AC0C89D00671115 /* libicucore.dylib */; }; + 008F07F31AC5B25A0029DE68 /* main.jsbundle in Resources */ = {isa = PBXBuildFile; fileRef = 008F07F21AC5B25A0029DE68 /* main.jsbundle */; }; + 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; + 00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */; }; + 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; + 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; + 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; + 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; + 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; + 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; + 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; + BBB2D57B1AD5AC80000BA10D /* libRCTVideo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BBB2D5791AD5ABDE000BA10D /* libRCTVideo.a */; }; + BBFFBEC21AD5A1DE004DC971 /* broadchurch.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = BBFFBEC11AD5A1CC004DC971 /* broadchurch.mp4 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 00481BE51AC0C7FA00671115 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; + remoteInfo = RCTWebSocketDebugger; + }; + 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTActionSheet; + }; + 00C302B31ABCB8E700DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; + remoteInfo = RCTAdSupport; + }; + 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTGeolocation; + }; + 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B5115D1A9E6B3D00147676; + remoteInfo = RCTImage; + }; + 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B511DB1A9E6C8500147676; + remoteInfo = RCTNetwork; + }; + 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; + remoteInfo = RCTVibration; + }; + 146834031AC3E56700842450 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; + remoteInfo = React; + }; + 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B5119B1A9E6C1200147676; + remoteInfo = RCTText; + }; + BBB2D5781AD5ABDE000BA10D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BBB2D5741AD5ABDE000BA10D /* RCTVideo.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTVideo; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocketDebugger.xcodeproj; path = "node_modules/react-native/Libraries/RCTWebSocketDebugger/RCTWebSocketDebugger.xcodeproj"; sourceTree = ""; }; + 00481BE91AC0C89D00671115 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; }; + 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = main.jsbundle; path = iOS/main.jsbundle; sourceTree = ""; }; + 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; + 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = "node_modules/react-native/Libraries/AdSupport/RCTAdSupport.xcodeproj"; sourceTree = ""; }; + 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; + 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; + 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; + 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* VideoPlayer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VideoPlayer.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = iOS/AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = iOS/AppDelegate.m; sourceTree = ""; }; + 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = iOS/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = iOS/Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = iOS/main.m; sourceTree = ""; }; + 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; + 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; + BBB2D5741AD5ABDE000BA10D /* RCTVideo.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVideo.xcodeproj; path = "node_modules/react-native-video/RCTVideo.xcodeproj"; sourceTree = ""; }; + BBFFBEC11AD5A1CC004DC971 /* broadchurch.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = broadchurch.mp4; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BBB2D57B1AD5AC80000BA10D /* libRCTVideo.a in Frameworks */, + 00481BEA1AC0C89D00671115 /* libicucore.dylib in Frameworks */, + 146834051AC3E58100842450 /* libReact.a in Frameworks */, + 00481BE81AC0C86700671115 /* libRCTWebSocketDebugger.a in Frameworks */, + 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, + 00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */, + 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, + 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, + 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, + 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, + 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00481BDC1AC0C7FA00671115 /* Products */ = { + isa = PBXGroup; + children = ( + 00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302A81ABCB8CE00DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302B01ABCB8E700DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302B61ABCB90400DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302BC1ABCB91800DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302D41ABCB9D200DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302E01ABCB9EE00DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */, + ); + name = Products; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* VideoPlayer */ = { + isa = PBXGroup; + children = ( + BBFFBEC11AD5A1CC004DC971 /* broadchurch.mp4 */, + 008F07F21AC5B25A0029DE68 /* main.jsbundle */, + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.m */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, + 13B07FB71A68108700A75B9A /* main.m */, + ); + name = VideoPlayer; + sourceTree = ""; + }; + 146834001AC3E56700842450 /* Products */ = { + isa = PBXGroup; + children = ( + 146834041AC3E56700842450 /* libReact.a */, + ); + name = Products; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + BBB2D5741AD5ABDE000BA10D /* RCTVideo.xcodeproj */, + 146833FF1AC3E56700842450 /* React.xcodeproj */, + 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, + 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, + 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */, + 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, + 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, + 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */, + 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, + 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */, + 00481BE91AC0C89D00671115 /* libicucore.dylib */, + ); + name = Libraries; + sourceTree = ""; + }; + 832341B11AAA6A8300B99B32 /* Products */ = { + isa = PBXGroup; + children = ( + 832341B51AAA6A8300B99B32 /* libRCTText.a */, + ); + name = Products; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* VideoPlayer */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 83CBBA001A601CBA00E9B192 /* Products */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* VideoPlayer.app */, + ); + name = Products; + sourceTree = ""; + }; + BBB2D5751AD5ABDE000BA10D /* Products */ = { + isa = PBXGroup; + children = ( + BBB2D5791AD5ABDE000BA10D /* libRCTVideo.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 13B07F861A680F5B00A75B9A /* VideoPlayer */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "VideoPlayer" */; + buildPhases = ( + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = VideoPlayer; + productName = "Hello World"; + productReference = 13B07F961A680F5B00A75B9A /* VideoPlayer.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0610; + ORGANIZATIONNAME = Facebook; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "VideoPlayer" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */; + ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; + }, + { + ProductGroup = 00C302B01ABCB8E700DB3ED1 /* Products */; + ProjectRef = 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */; + }, + { + ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; + ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; + }, + { + ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; + ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; + }, + { + ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */; + ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; + }, + { + ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; + ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; + }, + { + ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */; + ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; + }, + { + ProductGroup = BBB2D5751AD5ABDE000BA10D /* Products */; + ProjectRef = BBB2D5741AD5ABDE000BA10D /* RCTVideo.xcodeproj */; + }, + { + ProductGroup = 00481BDC1AC0C7FA00671115 /* Products */; + ProjectRef = 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */; + }, + { + ProductGroup = 146834001AC3E56700842450 /* Products */; + ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* VideoPlayer */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTWebSocketDebugger.a; + remoteRef = 00481BE51AC0C7FA00671115 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTActionSheet.a; + remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTAdSupport.a; + remoteRef = 00C302B31ABCB8E700DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTGeolocation.a; + remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTImage.a; + remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTNetwork.a; + remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTVibration.a; + remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 146834041AC3E56700842450 /* libReact.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libReact.a; + remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 832341B51AAA6A8300B99B32 /* libRCTText.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTText.a; + remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + BBB2D5791AD5ABDE000BA10D /* libRCTVideo.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTVideo.a; + remoteRef = BBB2D5781AD5ABDE000BA10D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BBFFBEC21AD5A1DE004DC971 /* broadchurch.mp4 in Resources */, + 008F07F31AC5B25A0029DE68 /* main.jsbundle in Resources */, + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, + 13B07FC11A68108700A75B9A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 13B07FB21A68108700A75B9A /* Base */, + ); + name = LaunchScreen.xib; + path = iOS; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/node_modules/react-native/React/**", + ); + INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = VideoPlayer; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/node_modules/react-native/React/**", + ); + INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = VideoPlayer; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* 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; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + 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; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/node_modules/react-native/React/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* 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; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + 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; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/node_modules/react-native/React/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "VideoPlayer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "VideoPlayer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..4ac4c91f --- /dev/null +++ b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcshareddata/VideoPlayer.xccheckout b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcshareddata/VideoPlayer.xccheckout new file mode 100644 index 00000000..6ce4fd2f --- /dev/null +++ b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcshareddata/VideoPlayer.xccheckout @@ -0,0 +1,41 @@ + + + + + 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 new file mode 100644 index 00000000..c93a7154 Binary files /dev/null and b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcuserdata/brentvatne.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme new file mode 100644 index 00000000..b089e027 --- /dev/null +++ b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 new file mode 100644 index 00000000..b1a4c519 --- /dev/null +++ b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 00000000..bc98ef59 --- /dev/null +++ b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + VideoPlayer.xcscheme_^#shared#^_ + + orderHint + 0 + + + SuppressBuildableAutocreation + + 13B07F861A680F5B00A75B9A + + primary + + + + + diff --git a/Examples/VideoPlayer/broadchurch.mp4 b/Examples/VideoPlayer/broadchurch.mp4 new file mode 100644 index 00000000..f729b6f2 Binary files /dev/null and b/Examples/VideoPlayer/broadchurch.mp4 differ diff --git a/Examples/VideoPlayer/iOS/AppDelegate.h b/Examples/VideoPlayer/iOS/AppDelegate.h new file mode 100644 index 00000000..a9654d5e --- /dev/null +++ b/Examples/VideoPlayer/iOS/AppDelegate.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +@interface AppDelegate : UIResponder + +@property (nonatomic, strong) UIWindow *window; + +@end diff --git a/Examples/VideoPlayer/iOS/AppDelegate.m b/Examples/VideoPlayer/iOS/AppDelegate.m new file mode 100644 index 00000000..3f7fb409 --- /dev/null +++ b/Examples/VideoPlayer/iOS/AppDelegate.m @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "AppDelegate.h" + +#import "RCTRootView.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + NSURL *jsCodeLocation; + + // Loading JavaScript code - uncomment the one you want. + + // OPTION 1 + // Load from development server. Start the server from the repository root: + // + // $ npm start + // + // To run on device, change `localhost` to the IP address of your computer, and make sure your computer and + // iOS device are on the same Wi-Fi network. + jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"]; + + // OPTION 2 + // Load from pre-bundled file on disk. To re-generate the static bundle, run + // + // $ curl 'http://localhost:8081/index.ios.bundle?dev=false&minify=true' -o iOS/main.jsbundle + // + // and uncomment the next following line + // jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; + + RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation + moduleName:@"VideoPlayer" + launchOptions:launchOptions]; + + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + UIViewController *rootViewController = [[UIViewController alloc] init]; + rootViewController.view = rootView; + self.window.rootViewController = rootViewController; + [self.window makeKeyAndVisible]; + return YES; +} + +@end diff --git a/Examples/VideoPlayer/iOS/Base.lproj/LaunchScreen.xib b/Examples/VideoPlayer/iOS/Base.lproj/LaunchScreen.xib new file mode 100644 index 00000000..187346b0 --- /dev/null +++ b/Examples/VideoPlayer/iOS/Base.lproj/LaunchScreen.xib @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/VideoPlayer/iOS/Images.xcassets/AppIcon.appiconset/Contents.json b/Examples/VideoPlayer/iOS/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..118c98f7 --- /dev/null +++ b/Examples/VideoPlayer/iOS/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Examples/VideoPlayer/iOS/Info.plist b/Examples/VideoPlayer/iOS/Info.plist new file mode 100644 index 00000000..c6d2494c --- /dev/null +++ b/Examples/VideoPlayer/iOS/Info.plist @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/Examples/VideoPlayer/iOS/main.jsbundle b/Examples/VideoPlayer/iOS/main.jsbundle new file mode 100644 index 00000000..4f50ea33 --- /dev/null +++ b/Examples/VideoPlayer/iOS/main.jsbundle @@ -0,0 +1,5 @@ +// Offline JS +// To re-generate the offline bundle, run this from root of your project +// $ curl 'http://localhost:8081/index.ios.bundle?dev=false&minify=true' -o iOS/main.jsbundle + +throw new Error('Offline JS file is empty. See iOS/main.jsbundle for instructions'); diff --git a/Examples/VideoPlayer/iOS/main.m b/Examples/VideoPlayer/iOS/main.m new file mode 100644 index 00000000..cb502bc1 --- /dev/null +++ b/Examples/VideoPlayer/iOS/main.m @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} + diff --git a/Examples/VideoPlayer/index.ios.js b/Examples/VideoPlayer/index.ios.js new file mode 100644 index 00000000..e8a51beb --- /dev/null +++ b/Examples/VideoPlayer/index.ios.js @@ -0,0 +1,206 @@ +/** + * Sample React Native App + * https://github.com/facebook/react-native + */ +'use strict'; + +var React = require('react-native'); +var { + AppRegistry, + StyleSheet, + Text, + View, + TouchableOpacity, +} = React; + +var Video = require('react-native-video'); + +var VideoPlayer = React.createClass({ + getInitialState() { + return { + rate: 1, + volume: 1, + muted: false, + resizeMode: 'contain', + duration: 0.0, + currentTime: 0.0, + } + }, + + onLoad(data) { + this.setState({duration: data.duration}); + }, + + onProgress(data) { + this.setState({currentTime: data.currentTime}); + }, + + getCurrentTimePercentage() { + if (this.state.currentTime > 0) { + return parseFloat(this.state.currentTime) / parseFloat(this.state.duration); + } else { + return 0; + } + }, + + renderRateControl(rate) { + var isSelected = (this.state.rate == rate); + + return ( + { this.setState({rate: rate}) }}> + + {rate}x + + + ) + }, + + renderResizeModeControl(resizeMode) { + var isSelected = (this.state.resizeMode == resizeMode); + + return ( + { this.setState({resizeMode: resizeMode}) }}> + + {resizeMode} + + + ) + }, + + renderVolumeControl(volume) { + var isSelected = (this.state.volume == volume); + + return ( + { this.setState({volume: volume}) }}> + + {volume * 100}% + + + ) + }, + + render() { + var flexCompleted = this.getCurrentTimePercentage() * 100; + var flexRemaining = (1 - this.getCurrentTimePercentage()) * 100; + + return ( + + {this.setState({paused: !this.state.paused})}}> + + + + + + {this.renderRateControl(0.25)} + {this.renderRateControl(0.5)} + {this.renderRateControl(1.0)} + {this.renderRateControl(1.5)} + {this.renderRateControl(2.0)} + + + + {this.renderVolumeControl(0.5)} + {this.renderVolumeControl(1)} + {this.renderVolumeControl(1.5)} + + + + {this.renderResizeModeControl('cover')} + {this.renderResizeModeControl('contain')} + {this.renderResizeModeControl('stretch')} + + + + + + + + + + + + ); + } +}); + + +var styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'black', + }, + video: { + position: 'absolute', + top: 0, + left: 0, + bottom: 0, + right: 0, + }, + controls: { + backgroundColor: "transparent", + borderRadius: 5, + position: 'absolute', + bottom: 20, + left: 20, + right: 20, + }, + progress: { + flex: 1, + flexDirection: 'row', + borderRadius: 3, + overflow: 'hidden', + }, + innerProgressCompleted: { + height: 20, + backgroundColor: '#cccccc', + }, + innerProgressRemaining: { + height: 20, + backgroundColor: '#2C2C2C', + }, + generalControls: { + flex: 1, + flexDirection: 'row', + borderRadius: 4, + overflow: 'hidden', + paddingBottom: 10, + }, + rateControl: { + flex: 1, + flexDirection: 'row', + justifyContent: 'center', + }, + volumeControl: { + flex: 1, + flexDirection: 'row', + justifyContent: 'center', + }, + resizeModeControl: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + controlOption: { + alignSelf: 'center', + fontSize: 11, + color: "white", + paddingLeft: 2, + paddingRight: 2, + lineHeight: 12, + }, +}); + +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 new file mode 100644 index 00000000..e6ddaaf1 --- /dev/null +++ b/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/project.pbxproj @@ -0,0 +1,260 @@ +// !$*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/node_modules/react-native-video/RCTVideo.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/RCTVideo.xcscheme b/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/RCTVideo.xcscheme new file mode 100644 index 00000000..1c5bd701 --- /dev/null +++ b/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/RCTVideo.xcscheme @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist b/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 00000000..0121e4b0 --- /dev/null +++ b/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + RCTVideo.xcscheme + + orderHint + 2 + + + SuppressBuildableAutocreation + + 58B511DA1A9E6C8500147676 + + primary + + + + + diff --git a/Examples/VideoPlayer/package.json b/Examples/VideoPlayer/package.json new file mode 100644 index 00000000..bf99f931 --- /dev/null +++ b/Examples/VideoPlayer/package.json @@ -0,0 +1,12 @@ +{ + "name": "VideoPlayer", + "version": "0.0.1", + "private": true, + "scripts": { + "start": "node_modules/react-native/packager/packager.sh" + }, + "dependencies": { + "react-native": "0.3.4", + "react-native-video": "^0.2.4" + } +} diff --git a/RCTVideo.h b/RCTVideo.h index 1fc82e43..a2888ad0 100644 --- a/RCTVideo.h +++ b/RCTVideo.h @@ -1,5 +1,10 @@ #import "RCTView.h" +extern NSString *const RNVideoEventLoaded; +extern NSString *const RNVideoEventLoading; +extern NSString *const RNVideoEventProgress; +extern NSString *const RNVideoEventLoadingError; + @class RCTEventDispatcher; @interface RCTVideo : UIView diff --git a/RCTVideo.m b/RCTVideo.m index ceb74afc..18a658c8 100644 --- a/RCTVideo.m +++ b/RCTVideo.m @@ -1,3 +1,4 @@ +#import "RCTConvert.h" #import "RCTVideo.h" #import "RCTLog.h" #import "RCTBridgeModule.h" @@ -5,9 +6,17 @@ #import "UIView+React.h" #import +NSString *const RNVideoEventLoaded = @"videoLoaded"; +NSString *const RNVideoEventLoading = @"videoLoading"; +NSString *const RNVideoEventProgress = @"videoProgress"; +NSString *const RNVideoEventLoadingError = @"videoLoadError"; + +static NSString *const statusKeyPath = @"status"; + @implementation RCTVideo { AVPlayer *_player; + AVPlayerItem *_playerItem; AVPlayerLayer *_playerLayer; NSURL *_videoURL; @@ -25,48 +34,61 @@ BOOL _muted; } -- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher -{ +- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher { if ((self = [super init])) { _eventDispatcher = eventDispatcher; - - /* Initialize videoProgress status publisher */ - _progressUpdateInterval = 250; - _prevProgressUpdateTime = nil; - _progressUpdateTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(sendProgressUpdate)]; - [_progressUpdateTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; + _rate = 1.0; + _volume = 1.0; } return self; } -- (void)sendProgressUpdate -{ +#pragma mark - Progress + +- (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:@{ + if (_prevProgressUpdateTime == nil || + (([_prevProgressUpdateTime timeIntervalSinceNow] * -1000.0) >= _progressUpdateInterval)) { + [_eventDispatcher sendInputEventWithName:RNVideoEventProgress body:@{ @"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(video.currentTime)], @"target": self.reactTag }]; + _prevProgressUpdateTime = [NSDate date]; } } -- (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)stopProgressTimer { + [_progressUpdateTimer invalidate]; +} + +- (void)startProgressTimer { + _progressUpdateInterval = 250; + _prevProgressUpdateTime = nil; + + [self stopProgressTimer]; + + _progressUpdateTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(sendProgressUpdate)]; + [_progressUpdateTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; +} + +#pragma mark - Player and source + +- (void)setSrc:(NSDictionary *)source { + [_playerItem removeObserver:self forKeyPath:statusKeyPath]; + _playerItem = [self playerItemForSource:source]; + [_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,37 +96,88 @@ [self.layer addSublayer:_playerLayer]; self.layer.needsDisplayOnBoundsChange = YES; - AVPlayerItem *video = [_player currentItem]; - - [_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], + [_eventDispatcher sendInputEventWithName:RNVideoEventLoading body:@{ + @"src": @{ + @"uri": [source objectForKey:@"uri"], + @"type": [source objectForKey:@"type"], + @"isNetwork":[NSNumber numberWithBool:(bool)[source objectForKey:@"isNetwork"]] + }, @"target": self.reactTag }]; - - [_player play]; - - /* rate and volume must be set after play is called */ - [self applyModifiers]; } -- (void)setResizeMode:(NSString*)mode -{ +- (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 { + if (object == _playerItem) { + if (_playerItem.status == AVPlayerItemStatusReadyToPlay) { + [_eventDispatcher sendInputEventWithName:RNVideoEventLoaded 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 + }]; + + [self startProgressTimer]; + [_player play]; + [self applyModifiers]; + } else if(_playerItem.status == AVPlayerItemStatusFailed) { + [_eventDispatcher sendInputEventWithName:RNVideoEventLoadingError 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)playerItemDidReachEnd:(NSNotification *)notification { + AVPlayerItem *item = [notification object]; + [item seekToTime:kCMTimeZero]; + [_player play]; + [self applyModifiers]; +} + +#pragma mark - Prop setters + +- (void)setResizeMode:(NSString*)mode { _playerLayer.videoGravity = mode; } - (void)setPaused:(BOOL)paused { if (paused) { + [self stopProgressTimer]; [_player pause]; } else { + [self startProgressTimer]; [_player play]; + } } @@ -127,8 +200,7 @@ - (void)applyModifiers { - /* volume must be set to 0 if muted is YES, or the video seems to - * freeze */ + /* volume must be set to 0 if muted is YES, or the video freezes playback */ if (_muted) { [_player setVolume:0]; [_player setMuted:YES]; @@ -140,14 +212,6 @@ [_player setRate:_rate]; } -- (void)playerItemDidReachEnd:(NSNotification *)notification { - AVPlayerItem *item = [notification object]; - [item seekToTime:kCMTimeZero]; - [_player play]; - [self applyModifiers]; -} - - - (void)setRepeatEnabled { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidReachEnd:) @@ -159,8 +223,7 @@ [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (void)setRepeat:(BOOL)repeat -{ +- (void)setRepeat:(BOOL)repeat { if (repeat) { [self setRepeatEnabled]; } else { @@ -168,24 +231,25 @@ } } -- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex -{ +#pragma mark - React View Management + +- (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; } +#pragma mark - Lifecycle + - (void)removeFromSuperview { [_player pause]; @@ -194,6 +258,7 @@ _player = nil; _prevProgressUpdateTime = nil; _eventDispatcher = nil; + [_playerItem removeObserver:self forKeyPath:statusKeyPath]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } diff --git a/RCTVideoManager.m b/RCTVideoManager.m index 27fa5209..008d1f5f 100644 --- a/RCTVideoManager.m +++ b/RCTVideoManager.m @@ -17,16 +17,22 @@ - (NSDictionary *)customDirectEventTypes { return @{ - @"videoLoaded": @{ + RNVideoEventLoading: @{ + @"registrationName": @"onLoadStart" + }, + RNVideoEventLoaded: @{ @"registrationName": @"onLoad" }, - @"videoProgress": @{ + RNVideoEventLoadingError: @{ + @"registrationName": @"onError" + }, + RNVideoEventProgress: @{ @"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); diff --git a/Video.ios.js b/Video.ios.js index 1647ccad..706096a7 100644 --- a/Video.ios.js +++ b/Video.ios.js @@ -10,18 +10,23 @@ 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, + // should probably be a shape + source: PropTypes.object, 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 +37,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,13 +56,15 @@ 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 isAsset = !!(source.uri && source.uri.match(/^assets-library:/)); var resizeMode; if (this.props.resizeMode === VideoResizeMode.stretch) { resizeMode = NativeModules.VideoManager.ScaleToFill; } else if (this.props.resizeMode === VideoResizeMode.contain) { resizeMode = NativeModules.VideoManager.ScaleAspectFit; - } else if (this.props.resizeMode == VideoResizeMode.cover) { + } else if (this.props.resizeMode === VideoResizeMode.cover) { resizeMode = NativeModules.VideoManager.ScaleAspectFill; } else { resizeMode = NativeModules.VideoManager.ScaleNone; @@ -58,9 +73,15 @@ var Video = React.createClass({ var nativeProps = merge(this.props, { style, resizeMode: resizeMode, - src: source, + src: { + uri: source.uri, + isNetwork, + isAsset, + type: source.type || 'mp4' + }, onLoad: this._onLoad, onProgress: this._onProgress, + }); return @@ -69,8 +90,8 @@ var Video = React.createClass({ var RCTVideo = createReactIOSNativeComponentClass({ validAttributes: merge(ReactIOSViewAttributes.UIView, - {src: true, resizeMode: true, repeat: true, paused: true, muted: true, - volume: true, rate: true}), + {src: {diff: deepDiffer}, resizeMode: true, repeat: true, + paused: true, muted: true, volume: true, rate: true}), uiViewClassName: 'RCTVideo', }); diff --git a/package.json b/package.json index fa9d0ad6..6536b243 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "Video.ios.js", "author": "Brent Vatne (https://github.com/brentvatne)", "dependencies": { - "react-native": "^0.3.1" + "react-native": "^0.3.5" }, "repository": { "type": "git",