79 Commits

Author SHA1 Message Date
Rogerio de Paula Assis 0ca7258e9b VIM-6919: Release 2.0.0, Swift 4.2 migration (#65) 2019-04-25 17:15:30 -04:00
Rogerio de Paula Assis a53096df50 Merge pull request #63 from vimeo/release/1.4.0
VIM-6919: Release 1.4.0 prior to migration to Swift 4.2
2019-04-24 16:44:43 -04:00
Rogerio de Paula Assis 4720991d0f VIM-6919 Version bump 1.4.0, added version_bump lane to fastlane 2019-04-23 13:24:00 -04:00
Rogerio de Paula Assis ca661f1996 Merge pull request #62 from vimeo/master
VIM-XXXX: Merge master into develop
2019-04-23 13:16:50 -04:00
Jason Hawkins 5ba8f4db04 Merge pull request #52 from vimeo/tech/add-swiftlint-support
Adds initial SwiftLint rules to PlayerKit
2018-11-28 10:09:18 -05:00
Jason Hawkins 34c5cac889 Build with swiftlint for example project files 2018-11-15 12:38:29 -05:00
Jason Hawkins 3729921bed Add example project files to included file paths for linting 2018-11-15 12:38:15 -05:00
Jason Hawkins ce3a42f41a Build with swiftlint for source files 2018-11-15 12:33:51 -05:00
Jason Hawkins 92e00745d7 Run bundle exec pod install 2018-11-15 12:32:42 -05:00
Jason Hawkins c7ef4c2ebc Add new script phase to example project 2018-11-15 12:31:35 -05:00
Jason Hawkins 75b2a10881 Add .swiftlint.yml 2018-11-15 12:31:22 -05:00
Jason Hawkins e60bd3bd3b Add SwiftLint to podfile 2018-11-15 12:31:11 -05:00
Nicole Lehrer a95c54eb56 Merge pull request #51 from vimeo/nicolelehrer-patch-1
Update README
2018-11-12 13:56:14 -05:00
Nicole Lehrer af54544cbe Update README.md 2018-11-12 12:56:55 -05:00
Mike Westendorf 54003387d5 Merge pull request #50 from vimeo/vim-6695-update-nokogiri
VIM-6695: Update nokogiri to v1.8.5
2018-11-08 15:08:26 -05:00
Mike Westendorf f441a7a03e update Gem lock file 2018-11-07 16:08:06 -05:00
Mike Westendorf ad04383a32 Update nokogiri to v1.8.5 2018-11-07 16:04:44 -05:00
Jason Hawkins 46d34ae58f Merge pull request #48 from vimeo/circle-ci-upgrade
AF-311: Updates PlayerKit to support CircleCI 2.0
2018-10-19 11:58:54 -04:00
jasonhawkins 6dce0ee5b4 Fix Xcode version number 2018-10-11 16:50:52 -04:00
jasonhawkins a9a9627ce9 Run bundle exec pod install 2018-10-11 16:49:39 -04:00
jasonhawkins 70eb3f5039 Update README 2018-10-11 16:49:31 -04:00
jasonhawkins b3ec050d8f Udpate Fastfaline to run against Xcode 10 2018-10-11 16:49:18 -04:00
jasonhawkins bea45df706 Update Podfile to specify a platform for the example 2018-10-11 16:48:58 -04:00
jasonhawkins 03482bccda Update CircleCI to execute our custom scan lane 2018-10-11 16:48:19 -04:00
jasonhawkins 01f34b57e5 Update CircleCI to run against Xcode 10 2018-10-11 16:48:05 -04:00
jasonhawkins a83cf1fb3a Remove embed swift libraries override
CocoaPods will do this for us anyway.
2018-10-11 16:47:42 -04:00
jasonhawkins 1b09629f9d Remove _Pods alias 2018-08-27 16:34:21 -04:00
jasonhawkins 97f17e3362 Remove old CircleCi config 2018-08-27 16:22:46 -04:00
jasonhawkins 72aec6efa8 Add new CircleCi config 2018-08-27 16:22:36 -04:00
jasonhawkins 708c945840 Run bundle exec pod install 2018-08-27 16:22:25 -04:00
Frederick Kellison-Linn a60a1da448 Merge pull request #39 from vimeo/master
Update develop for 1.3.0 release
2018-07-18 16:24:41 -04:00
Frederick Kellison-Linn 90530c4961 Merge pull request #38 from vimeo/release/1.3.0
Release 1.3.0
2018-07-18 15:57:49 -04:00
Freddy Kellison-Linn 7f7f2157fd Release 1.3.0 2018-07-18 15:42:21 -04:00
Freddy Kellison-Linn 2a11f34165 Add explanatory comment for SDH 2018-07-18 15:42:21 -04:00
Freddy Kellison-Linn 0a28c0cc1b Use new matches(_:) method in select(_:) 2018-07-18 15:42:21 -04:00
Freddy Kellison-Linn a31eafca1f Fixup style 2018-07-18 15:42:21 -04:00
Freddy Kellison-Linn 6e8446675e Change == operator to matches(_:) method 2018-07-18 15:42:21 -04:00
Freddy Kellison-Linn dd3f9937b2 Make TextTrackMetadata == global 2018-07-18 15:42:21 -04:00
Freddy Kellison-Linn fb7879346a Improve TextTrackMetadata and TextTrackCapable APIs 2018-07-18 15:42:21 -04:00
Freddy Kellison-Linn 393e659cf0 Remove deprecated API in newer versions 2018-07-18 15:42:21 -04:00
Freddy Kellison-Linn 17c04841dd Add selectedTrack requirement to TextTrackCapable 2018-07-18 15:42:21 -04:00
Freddy Kellison-Linn 19328921bb Use Array.first instead of for-in loop 2018-07-18 15:42:21 -04:00
Freddy Kellison-Linn 14f1e26dfd Move TextTrackCapable conformance to extension 2018-07-18 15:42:21 -04:00
Freddy Kellison-Linn a031f37000 Make RegularPlayer conform to TextTrackCapable and AVMediaSelectionOption to TextTrackMetadata 2018-07-18 15:42:20 -04:00
Freddy Kellison-Linn ceeb22419f Add period 2018-07-18 15:42:20 -04:00
Freddy Kellison-Linn c02d5aba36 Add TextTrackMetadata and TextTrackCapable protocols to Player.swift 2018-07-18 15:42:20 -04:00
Mike Westendorf 9490ecc197 updates cocoapods to version 1.5.2, updates git ignore file 2018-07-18 15:42:20 -04:00
Frederick Kellison-Linn 56946a6509 Merge pull request #37 from vimeo/feature/VIM-6303-closed-captions
Merge feature work for Closed Captions into develop
2018-07-18 15:13:30 -04:00
Frederick Kellison-Linn 0b9d4e5096 Merge pull request #36 from vimeo/VIM-6350-select-cc-option
VIM-6350: Turn on/off CC when user taps appropriate item in list
2018-07-11 13:05:24 -04:00
Freddy Kellison-Linn 3a53693935 Add explanatory comment for SDH 2018-07-11 11:58:27 -04:00
Freddy Kellison-Linn aee3f617d6 Use new matches(_:) method in select(_:) 2018-07-10 15:57:25 -04:00
Freddy Kellison-Linn 41f59b1d45 Fixup style 2018-07-10 15:51:46 -04:00
Freddy Kellison-Linn 978efdb667 Change == operator to matches(_:) method 2018-07-10 15:08:57 -04:00
Freddy Kellison-Linn d9f3f12bb8 Make TextTrackMetadata == global 2018-07-10 14:38:29 -04:00
Freddy Kellison-Linn aecc7485a5 Improve TextTrackMetadata and TextTrackCapable APIs 2018-07-10 14:09:41 -04:00
Freddy Kellison-Linn 09a1d6a051 Remove deprecated API in newer versions 2018-07-10 12:27:02 -04:00
Freddy Kellison-Linn 8280e5e801 Add selectedTrack requirement to TextTrackCapable 2018-07-09 14:40:39 -04:00
Frederick Kellison-Linn f2d24ffb2e Merge pull request #35 from vimeo/VIM-6353-regularplayer-conform-texttrackcapable
VIM-6353: Make RegularPlayer conform to `TextTrackCapable`
2018-07-05 10:45:37 -04:00
Freddy Kellison-Linn b1b690d6ad Use Array.first instead of for-in loop 2018-07-05 10:15:48 -04:00
Freddy Kellison-Linn fa9fa737d5 Move TextTrackCapable conformance to extension 2018-07-03 10:22:00 -04:00
Freddy Kellison-Linn fae36bc646 Make RegularPlayer conform to TextTrackCapable and AVMediaSelectionOption to TextTrackMetadata 2018-07-02 15:55:56 -04:00
Frederick Kellison-Linn 055c6b727a Merge pull request #34 from vimeo/VIM-6347-texttrack-player-protocols
Add TextTrackMetadata and TextTrackCapable protocols to Player.swift
2018-07-02 15:53:08 -04:00
Freddy Kellison-Linn 3e945f1639 Add period 2018-07-02 15:44:15 -04:00
Freddy Kellison-Linn bc804d729a Add TextTrackMetadata and TextTrackCapable protocols to Player.swift 2018-06-28 15:47:24 -04:00
Mike Westendorf 7222d585e5 Merge pull request #33 from vimeo/vim-xxx-updates-cocoapods
VIM-6140: Update CocoaPods to version 1.5.2
2018-06-04 13:52:42 -04:00
Mike Westendorf 365b835447 updates cocoapods to version 1.5.2, updates git ignore file 2018-05-24 13:51:35 -04:00
Gavin King d9fd6ec9e0 Merge pull request #24 from vimeo/develop
Merging master into develop
2017-12-07 16:27:04 -05:00
Gavin King 1d5a54e427 Merge pull request #23 from vimeo/VIM-XXX-swift-version
Update .swift-version
2017-12-07 16:24:31 -05:00
Gavin King 9e72e81f44 Update .swift-version 2017-12-07 16:19:10 -05:00
Gavin King bd27ed90de Merge pull request #22 from vimeo/develop
Merging develop into master
2017-12-07 16:02:01 -05:00
Gavin King 0be337a29f Merge pull request #21 from vimeo/AF-210-swift-4
AF-210: Swift 4
2017-12-07 16:00:55 -05:00
Gavin King 15933a66a3 fastlane 2017-11-29 17:12:08 -05:00
Gavin King 57533faa36 example version increment 2017-11-29 17:09:41 -05:00
Gavin King 5067393d78 inference 2017-11-29 17:08:35 -05:00
Gavin King 0245cf6f8b version increment 2017-11-29 16:55:38 -05:00
Gavin King c0e553dcbf @objc 2017-11-29 16:54:40 -05:00
Gavin King c15d31d6af migration and FillModeCapable changes 2017-11-29 16:18:45 -05:00
Gavin King 3981702cfe minimum requirements 2017-10-09 11:14:18 -04:00
Gavin King c057324b82 Update README.md 2017-10-06 17:04:18 -04:00
25 changed files with 464 additions and 365 deletions
+50
View File
@@ -0,0 +1,50 @@
version: 2
jobs:
build-and-test:
environment:
BUNDLE_PATH: vendor/bundle
FL_OUTPUT_DIR: output
macos:
xcode: "10.1.0"
working_directory: ~/PlayerKit
shell: /bin/bash --login -o pipefail
steps:
- checkout
- restore_cache:
key: v1-gems-{{ checksum "Gemfile.lock" }}
- run:
name: Set Ruby version
command: echo "ruby-2.4" > ~/.ruby-version
- run:
name: Install bundler dependencies
command: bundle install --path vendor/bundle
- run:
name: Build and run tests
command: bundle exec fastlane ios test
environment:
SCAN_DEVICE: iPhone 8
SCAN_SCHEME: PlayerKit-Example
- save_cache:
paths:
- vendor/bundle
key: v1-gems-{{ checksum "Gemfile.lock" }}
- store_artifacts:
path: output
- store_test_results:
path: output/scan
workflows:
version: 2
build:
jobs:
- build-and-test
+1
View File
@@ -21,6 +21,7 @@ xcuserdata/
*.moved-aside
*.xccheckout
*.xcscmblueprint
.DS_Store
## Obj-C/Swift specific
*.hmap
-1
View File
@@ -1 +0,0 @@
3.2
+42
View File
@@ -0,0 +1,42 @@
# Copyright © 2018 Vimeo. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Run `swiftlint rules` for a list of available rules.
# Only the rules specified here will be enabled.
whitelist_rules:
- trailing_newline
- trailing_whitespace
- opening_brace
# Paths to include during linting.
included:
- ../PlayerKit/Classes
- ../Example
# Paths to exclude during linting.
excluded:
- Pods
# Configurable rules can be customized from this configuration file,
# binary rules can set their severity level.
trailing_whitespace:
ignores_empty_lines: true
+19 -49
View File
@@ -172,9 +172,9 @@
39DBB93200760D1BB486C4CC /* [CP] Check Pods Manifest.lock */,
607FACCC1AFB9204008FA782 /* Sources */,
607FACCD1AFB9204008FA782 /* Frameworks */,
0C1455B6219DDFB7006442F3 /* ShellScript */,
607FACCE1AFB9204008FA782 /* Resources */,
AEEB7FDEAB18BB5B2C3B7E51 /* [CP] Embed Pods Frameworks */,
321F705B84CEA2E392A6B199 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -193,8 +193,6 @@
607FACE11AFB9204008FA782 /* Sources */,
607FACE21AFB9204008FA782 /* Frameworks */,
607FACE31AFB9204008FA782 /* Resources */,
25C5F87D98E09CBD3E2CA814 /* [CP] Embed Pods Frameworks */,
3C28040621F8BDAC7AF4AA8F /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -219,12 +217,12 @@
607FACCF1AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
DevelopmentTeam = 35R365FS4Q;
LastSwiftMigration = 0820;
LastSwiftMigration = 1010;
};
607FACE41AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
DevelopmentTeam = 35R365FS4Q;
LastSwiftMigration = 0820;
LastSwiftMigration = 1010;
TestTargetID = 607FACCF1AFB9204008FA782;
};
};
@@ -234,6 +232,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
@@ -270,35 +269,18 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
25C5F87D98E09CBD3E2CA814 /* [CP] Embed Pods Frameworks */ = {
0C1455B6219DDFB7006442F3 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PlayerKit_Tests/Pods-PlayerKit_Tests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
321F705B84CEA2E392A6B199 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PlayerKit_Example/Pods-PlayerKit_Example-resources.sh\"\n";
showEnvVarsInLog = 0;
shellScript = "WORKSPACE_ROOT=$( cd \"$(dirname \"${SRCROOT[0]}\")\" ; pwd -P )\n\nif which \"$PODS_ROOT\"/SwiftLint/swiftlint > /dev/null; then\n \"$PODS_ROOT\"/SwiftLint/swiftlint autocorrect --config \"$WORKSPACE_ROOT\"/.swiftlint.yml\nelse\n echo \"Warning: SwiftLint is not installed. Make sure you've run `bundle exec pod install`.\"\nfi\n";
};
39DBB93200760D1BB486C4CC /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
@@ -306,28 +288,16 @@
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-PlayerKit_Example-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
3C28040621F8BDAC7AF4AA8F /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PlayerKit_Tests/Pods-PlayerKit_Tests-resources.sh\"\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
AEEB7FDEAB18BB5B2C3B7E51 /* [CP] Embed Pods Frameworks */ = {
@@ -336,9 +306,12 @@
files = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-PlayerKit_Example/Pods-PlayerKit_Example-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/PlayerKit/PlayerKit.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PlayerKit.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -351,13 +324,16 @@
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-PlayerKit_Tests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
@@ -446,7 +422,7 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_VERSION = 4.2;
};
name = Debug;
};
@@ -486,7 +462,7 @@
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
SWIFT_VERSION = 4.2;
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -495,7 +471,6 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 9D69DB7C6B7F626E6391E3FA /* Pods-PlayerKit_Example.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 35R365FS4Q;
INFOPLIST_FILE = PlayerKit/Info.plist;
@@ -503,7 +478,6 @@
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -512,7 +486,6 @@
isa = XCBuildConfiguration;
baseConfigurationReference = CF08222175BD5B0E142D343A /* Pods-PlayerKit_Example.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 35R365FS4Q;
INFOPLIST_FILE = PlayerKit/Info.plist;
@@ -520,7 +493,6 @@
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
@@ -539,7 +511,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
@@ -553,7 +524,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0820"
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -40,6 +40,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -69,6 +70,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
+1 -2
View File
@@ -13,8 +13,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = PlayerViewController()
self.window?.makeKeyAndVisible()
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>2.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
+14 -28
View File
@@ -10,10 +10,8 @@ import UIKit
import PlayerKit
import AVFoundation
class PlayerViewController: UIViewController, PlayerDelegate
{
private struct Constants
{
class PlayerViewController: UIViewController, PlayerDelegate {
private struct Constants {
static let VideoURL = URL(string: "https://github.com/vimeo/PlayerKit/blob/master/Example/PlayerKit/video.mp4?raw=true")!
}
@@ -24,8 +22,7 @@ class PlayerViewController: UIViewController, PlayerDelegate
private let player = RegularPlayer()
override func viewDidLoad()
{
override func viewDidLoad() {
super.viewDidLoad()
player.delegate = self
@@ -37,8 +34,7 @@ class PlayerViewController: UIViewController, PlayerDelegate
// MARK: Setup
private func addPlayerToView()
{
private func addPlayerToView() {
player.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
player.view.frame = self.view.bounds
self.view.insertSubview(player.view, at: 0)
@@ -46,13 +42,11 @@ class PlayerViewController: UIViewController, PlayerDelegate
// MARK: Actions
@IBAction func didTapPlayButton()
{
@IBAction func didTapPlayButton() {
self.player.playing ? self.player.pause() : self.player.play()
}
@IBAction func didChangeSliderValue()
{
@IBAction func didChangeSliderValue() {
let value = Double(self.slider.value)
let time = value * self.player.duration
@@ -62,12 +56,10 @@ class PlayerViewController: UIViewController, PlayerDelegate
// MARK: VideoPlayerDelegate
func playerDidUpdateState(player: Player, previousState: PlayerState)
{
func playerDidUpdateState(player: Player, previousState: PlayerState) {
self.activityIndicator.isHidden = true
switch player.state
{
switch player.state {
case .loading:
self.activityIndicator.isHidden = false
@@ -82,30 +74,24 @@ class PlayerViewController: UIViewController, PlayerDelegate
}
}
func playerDidUpdatePlaying(player: Player)
{
func playerDidUpdatePlaying(player: Player) {
self.playButton.isSelected = player.playing
}
func playerDidUpdateTime(player: Player)
{
guard player.duration > 0 else
{
func playerDidUpdateTime(player: Player) {
guard player.duration > 0 else {
return
}
let ratio = player.time / player.duration
if self.slider.isHighlighted == false
{
if self.slider.isHighlighted == false {
self.slider.value = Float(ratio)
}
}
func playerDidUpdateBufferedTime(player: Player)
{
guard player.duration > 0 else
{
func playerDidUpdateBufferedTime(player: Player) {
guard player.duration > 0 else {
return
}
+8 -6
View File
@@ -1,10 +1,12 @@
use_frameworks!
platform :ios, '8.0'
target 'PlayerKit_Example' do
pod 'PlayerKit', :path => '../'
target 'PlayerKit_Tests' do
inherit! :search_paths
end
pod 'PlayerKit', :path => '../'
pod 'SwiftLint', '0.28.0'
target 'PlayerKit_Tests' do
inherit! :search_paths
end
end
+12 -5
View File
@@ -1,16 +1,23 @@
PODS:
- PlayerKit (1.1.0)
- PlayerKit (1.3.0)
- SwiftLint (0.28.0)
DEPENDENCIES:
- PlayerKit (from `../`)
- SwiftLint (= 0.28.0)
SPEC REPOS:
https://github.com/cocoapods/specs.git:
- SwiftLint
EXTERNAL SOURCES:
PlayerKit:
:path: ../
:path: "../"
SPEC CHECKSUMS:
PlayerKit: 3f06187a533ce4e2a8aa29583e561b465d0d085e
PlayerKit: 16dbe4196fbd6cbc0e677026d13ffb5fb80276fb
SwiftLint: 088cfacb75b45970017e62b7524d506776d60148
PODFILE CHECKSUM: 071d8819500a822237123321021901352f4d91a4
PODFILE CHECKSUM: 90f31c00641fb4d5e9453ba687a3a06a32cca83f
COCOAPODS: 1.2.0
COCOAPODS: 1.5.2
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>2.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
+2 -2
View File
@@ -1,10 +1,10 @@
source 'https://rubygems.org'
gem 'fastlane', '2.42.0'
gem 'cocoapods', '1.2.0'
gem 'cocoapods', '1.5.2'
gem 'danger', '4.0.4'
gem 'xcode-install', '2.1.0'
gem 'xcpretty-json-formatter', '0.1.0'
gem 'danger-xcode_summary', '0.1.0'
gem 'nokogiri', '1.6.0'
gem 'nokogiri', '1.8.5'
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval(File.read(plugins_path), binding) if File.exist?(plugins_path)
+69 -65
View File
@@ -1,60 +1,62 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (2.3.5)
activesupport (4.2.9)
CFPropertyList (2.3.6)
activesupport (4.2.10)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
atomos (0.1.2)
babosa (1.0.2)
claide (1.0.2)
claide-plugins (0.9.2)
cork
nap
open4 (~> 1.3)
cocoapods (1.2.0)
cocoapods (1.5.2)
activesupport (>= 4.0.2, < 5)
claide (>= 1.0.1, < 2.0)
cocoapods-core (= 1.2.0)
cocoapods-deintegrate (>= 1.0.1, < 2.0)
cocoapods-downloader (>= 1.1.3, < 2.0)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.5.2)
cocoapods-deintegrate (>= 1.0.2, < 2.0)
cocoapods-downloader (>= 1.2.0, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-stats (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.1.2, < 2.0)
cocoapods-trunk (>= 1.3.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored (~> 1.2)
colored2 (~> 3.1)
escape (~> 0.0.4)
fourflusher (~> 2.0.1)
gh_inspector (~> 1.0)
molinillo (~> 0.5.5)
molinillo (~> 0.6.5)
nap (~> 1.0)
ruby-macho (~> 0.2.5)
xcodeproj (>= 1.4.1, < 2.0)
cocoapods-core (1.2.0)
activesupport (>= 4.0.2, < 5)
ruby-macho (~> 1.1)
xcodeproj (>= 1.5.7, < 2.0)
cocoapods-core (1.5.2)
activesupport (>= 4.0.2, < 6)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
cocoapods-deintegrate (1.0.1)
cocoapods-downloader (1.1.3)
cocoapods-deintegrate (1.0.2)
cocoapods-downloader (1.2.0)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.0)
cocoapods-stats (1.0.0)
cocoapods-trunk (1.2.0)
cocoapods-trunk (1.3.0)
nap (>= 0.8, < 2.0)
netrc (= 0.7.8)
netrc (~> 0.11)
cocoapods-try (1.1.0)
colored (1.2)
colored2 (3.1.2)
colorize (0.8.1)
commander-fastlane (4.4.5)
commander-fastlane (4.4.6)
highline (~> 1.7.2)
cork (0.2.0)
colored (~> 1.2)
concurrent-ruby (1.0.5)
cork (0.3.0)
colored2 (~> 3.1)
danger (4.0.4)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
@@ -70,23 +72,23 @@ GEM
danger (> 2.0)
danger-xcode_summary (0.1.0)
danger-plugin-api (~> 1.0)
declarative (0.0.9)
declarative (0.0.10)
declarative-option (0.1.0)
domain_name (0.5.20170404)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.2.1)
dotenv (2.4.0)
escape (0.0.4)
excon (0.57.1)
faraday (0.12.1)
excon (0.62.0)
faraday (0.15.2)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4)
http-cookie (~> 1.0.0)
faraday-http-cache (1.3.1)
faraday (~> 0.8)
faraday_middleware (0.11.0.1)
faraday_middleware (0.12.2)
faraday (>= 0.7.4, < 1.0)
fastimage (2.1.0)
fastimage (2.1.3)
fastlane (2.42.0)
CFPropertyList (>= 2.3, < 3.0.0)
addressable (>= 2.3, < 3.0.0)
@@ -125,8 +127,8 @@ GEM
terminal-table
fourflusher (2.0.1)
fuzzy_match (2.0.4)
gh_inspector (1.0.3)
git (1.3.0)
gh_inspector (1.1.3)
git (1.4.0)
google-api-client (0.12.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.5)
@@ -134,22 +136,23 @@ GEM
mime-types (~> 3.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
googleauth (0.5.1)
faraday (~> 0.9)
jwt (~> 1.4)
googleauth (0.6.2)
faraday (~> 0.12)
jwt (>= 1.4, < 3.0)
logging (~> 2.0)
memoist (~> 0.12)
multi_json (~> 1.11)
os (~> 0.9)
signet (~> 0.7)
highline (1.7.8)
highline (1.7.10)
http-cookie (1.0.3)
domain_name (~> 0.5)
httpclient (2.8.3)
i18n (0.8.6)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
json (2.1.0)
jwt (1.5.6)
kramdown (1.13.2)
jwt (2.1.0)
kramdown (1.16.2)
little-plugger (1.1.4)
logging (2.2.2)
little-plugger (~> 1.1)
@@ -159,81 +162,82 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_magick (4.5.1)
mini_portile (0.5.3)
minitest (5.10.2)
molinillo (0.5.7)
multi_json (1.12.1)
mini_portile2 (2.3.0)
minitest (5.11.3)
molinillo (0.6.5)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
nanaimo (0.2.3)
nanaimo (0.2.5)
nap (1.1.0)
netrc (0.7.8)
nokogiri (1.6.0)
mini_portile (~> 0.5.0)
octokit (4.6.2)
netrc (0.11.0)
nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
octokit (4.9.0)
sawyer (~> 0.8.0, >= 0.5.3)
open4 (1.3.4)
os (0.9.6)
plist (3.3.0)
public_suffix (2.0.5)
plist (3.4.0)
public_suffix (3.0.2)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
retriable (3.0.2)
retriable (3.1.1)
rouge (2.0.7)
ruby-macho (0.2.6)
ruby-macho (1.1.0)
rubyzip (1.2.1)
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
security (0.1.3)
signet (0.7.3)
signet (0.8.1)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (~> 1.5)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
slack-notifier (1.5.1)
terminal-notifier (1.8.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
tty-screen (0.5.0)
tzinfo (1.2.3)
tty-screen (0.5.1)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.4)
unicode-display_width (1.3.0)
unf_ext (0.0.7.5)
unicode-display_width (1.3.2)
word_wrap (1.0.0)
xcode-install (2.1.0)
claide (>= 0.9.1, < 1.1.0)
fastlane (>= 2.1.1, < 3.0.0)
xcodeproj (1.5.0)
CFPropertyList (~> 2.3.3)
xcodeproj (1.5.9)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.2)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.2.3)
nanaimo (~> 0.2.5)
xcpretty (0.2.8)
rouge (~> 2.0.7)
xcpretty-json-formatter (0.1.0)
xcpretty (~> 0.2, >= 0.0.7)
xcpretty-travis-formatter (0.0.4)
xcpretty-travis-formatter (1.0.0)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
DEPENDENCIES
cocoapods (= 1.2.0)
cocoapods (= 1.5.2)
danger (= 4.0.4)
danger-xcode_summary (= 0.1.0)
fastlane (= 2.42.0)
fastlane-plugin-pretty_junit
nokogiri (= 1.6.0)
nokogiri (= 1.8.5)
xcode-install (= 2.1.0)
xcpretty-json-formatter (= 0.1.0)
BUNDLED WITH
1.15.1
1.15.3
+3 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'PlayerKit'
s.version = '1.1.0'
s.version = '2.0.0'
s.summary = 'A modular video player system.'
s.description = <<-DESC
@@ -15,6 +15,8 @@ Pod::Spec.new do |s|
s.ios.deployment_target = '8.0'
s.tvos.deployment_target = '9.0'
s.swift_version = "4.2"
s.source_files = 'PlayerKit/Classes/**/*'
end
+6 -12
View File
@@ -9,30 +9,24 @@
import Foundation
import AVFoundation
extension AVPlayer
{
var errorForPlayerOrItem: NSError?
{
extension AVPlayer {
var errorForPlayerOrItem: NSError? {
// First try to return the current item's error
if let error = self.currentItem?.error
{
if let error = self.currentItem?.error {
// If current item's error has an underlying error, return that
if let underlyingError = (error as NSError).userInfo[NSUnderlyingErrorKey] as? NSError
{
if let underlyingError = (error as NSError).userInfo[NSUnderlyingErrorKey] as? NSError {
return underlyingError
}
else
{
else {
return error as NSError?
}
}
// Otherwise, try to return the player error
if let error = self.error
{
if let error = self.error {
return error as NSError?
}
+3 -6
View File
@@ -9,12 +9,9 @@
import Foundation
import AVFoundation
extension CMTime
{
var timeInterval: TimeInterval?
{
if CMTIME_IS_INVALID(self) || CMTIME_IS_INDEFINITE(self)
{
extension CMTime {
var timeInterval: TimeInterval? {
if CMTIME_IS_INVALID(self) || CMTIME_IS_INDEFINITE(self) {
return nil
}
+45 -26
View File
@@ -10,8 +10,7 @@ import UIKit
import AVKit
/// A player error
public enum PlayerError: Int
{
public enum PlayerError: Int {
case unknown
case loading
@@ -20,10 +19,8 @@ public enum PlayerError: Int
/// The associated error
///
/// - Returns: The error
public func error() -> NSError
{
switch self
{
public func error() -> NSError {
switch self {
case .unknown:
return NSError(domain: type(of: self).Domain, code: self.rawValue, userInfo: [NSLocalizedDescriptionKey: "An unknown error occurred."])
@@ -37,19 +34,17 @@ public enum PlayerError: Int
/// Represents the current state of the player
///
/// - Loading: The player is loading or buffering
/// - Ready: The player is ready for playback
/// - Failed: The player has failed
@objc public enum PlayerState: Int
{
/// - loading: The player is loading or buffering
/// - ready: The player is ready for playback
/// - failed: The player has failed
@objc public enum PlayerState: Int {
case loading
case ready
case failed
}
/// An object that adopts the PlayerDelegate protocol can receive updates from the player.
@objc public protocol PlayerDelegate: class
{
@objc public protocol PlayerDelegate: class {
func playerDidUpdateState(player: Player, previousState: PlayerState)
func playerDidUpdatePlaying(player: Player)
func playerDidUpdateTime(player: Player)
@@ -57,8 +52,7 @@ public enum PlayerError: Int
}
/// An object that adopts the Player protocol is responsible for implementing the API and calling PlayerDelegate methods where appropriate.
@objc public protocol Player: class
{
@objc public protocol Player: class {
weak var delegate: PlayerDelegate? { get set }
var state: PlayerState { get }
@@ -88,35 +82,60 @@ public enum PlayerError: Int
// MARK: Identity Protocols
/// A player that adopts the ProvidesView protocol is capable of providing a view to be added to a view hierarchy.
@objc public protocol ProvidesView
{
@objc public protocol ProvidesView {
var view: UIView { get }
}
// MARK: Capability Protocols
/// A player that adopts the ProvidesView protocol is capable of AirPlay playback.
@objc public protocol AirPlayCapable
{
@objc public protocol AirPlayCapable {
var isAirPlayEnabled: Bool { get set }
}
/// A player that adopts the ProvidesView protocol is capable of setting audio volume.
@objc public protocol VolumeCapable
{
@objc public protocol VolumeCapable {
var volume: Float { get set }
}
/// A player that adopts the ProvidesView protocol is capable of setting the video fill mode.
@objc public protocol FillModeCapable
{
var fillMode: String { get set }
@objc public protocol FillModeCapable {
var fillMode: FillMode { get set }
}
@objc public enum FillMode: Int {
case fit
case fill
}
/// The metadata that should be attached to any type of text track.
@objc public protocol TextTrackMetadata {
var displayName: String { get }
var locale: Locale? { get }
// Indicates that the text track represents subtitles for the def and hard of hearing (SDH).
var isSDHTrack: Bool { get }
@objc(displayNameWithLocale:) func displayName(with locale: Locale) -> String
}
extension TextTrackMetadata {
public func matches(_ other: TextTrackMetadata) -> Bool {
return (self.locale == other.locale && self.isSDHTrack == other.isSDHTrack)
}
}
/// A player that conforms to the TextTrackCapable protocol is capable of advertising and displaying text tracks.
@objc public protocol TextTrackCapable {
var selectedTextTrack: TextTrackMetadata? { get }
var availableTextTracks: [TextTrackMetadata] { get }
func fetchTextTracks(completion: @escaping ([TextTrackMetadata], TextTrackMetadata?) -> Void)
func select(_ textTrack: TextTrackMetadata?)
}
#if os(iOS)
/// A player that adopts the ProvidesView protocol is capable of Picture in Picture playback.
@objc public protocol PictureInPictureCapable
{
@objc public protocol PictureInPictureCapable {
@available(iOS 9.0, *)
var pictureInPictureController: AVPictureInPictureController? { get }
}
+140 -130
View File
@@ -11,11 +11,15 @@ import Foundation
import AVFoundation
import AVKit
extension AVMediaSelectionOption: TextTrackMetadata {
public var isSDHTrack: Bool {
return self.hasMediaCharacteristic(.describesMusicAndSoundForAccessibility) && self.hasMediaCharacteristic(.transcribesSpokenDialogForAccessibility)
}
}
/// A RegularPlayer is used to play regular videos.
open class RegularPlayer: NSObject, Player, ProvidesView
{
public struct Constants
{
@objc open class RegularPlayer: NSObject, Player, ProvidesView {
public struct Constants {
public static let TimeUpdateInterval: TimeInterval = 0.1
}
@@ -28,12 +32,10 @@ open class RegularPlayer: NSObject, Player, ProvidesView
/// Sets an AVAsset on the player.
///
/// - Parameter asset: The AVAsset
open func set(_ asset: AVAsset)
{
@objc open func set(_ asset: AVAsset) {
// Prepare the old item for removal
if let currentItem = self.player.currentItem
{
if let currentItem = self.player.currentItem {
self.removePlayerItemObservers(fromPlayerItem: currentItem)
}
@@ -48,33 +50,27 @@ open class RegularPlayer: NSObject, Player, ProvidesView
// MARK: ProvidesView
private class RegularPlayerView: UIView
{
var playerLayer: AVPlayerLayer
{
private class RegularPlayerView: UIView {
var playerLayer: AVPlayerLayer {
return self.layer as! AVPlayerLayer
}
override class var layerClass: AnyClass
{
override class var layerClass: AnyClass {
return AVPlayerLayer.self
}
func configureForPlayer(player: AVPlayer)
{
func configureForPlayer(player: AVPlayer) {
(self.layer as! AVPlayerLayer).player = player
}
}
public let view: UIView = RegularPlayerView(frame: .zero)
private var regularPlayerView: RegularPlayerView
{
private var regularPlayerView: RegularPlayerView {
return self.view as! RegularPlayerView
}
private var playerLayer: AVPlayerLayer
{
private var playerLayer: AVPlayerLayer {
return self.regularPlayerView.playerLayer
}
@@ -82,68 +78,55 @@ open class RegularPlayer: NSObject, Player, ProvidesView
weak public var delegate: PlayerDelegate?
public private(set) var state: PlayerState = .ready
{
didSet
{
public private(set) var state: PlayerState = .ready {
didSet {
self.delegate?.playerDidUpdateState(player: self, previousState: oldValue)
}
}
public var duration: TimeInterval
{
public var duration: TimeInterval {
return self.player.currentItem?.duration.timeInterval ?? 0
}
public private(set) var time: TimeInterval = 0
{
didSet
{
public private(set) var time: TimeInterval = 0 {
didSet {
self.delegate?.playerDidUpdateTime(player: self)
}
}
public private(set) var bufferedTime: TimeInterval = 0
{
didSet
{
public private(set) var bufferedTime: TimeInterval = 0 {
didSet {
self.delegate?.playerDidUpdateBufferedTime(player: self)
}
}
public var playing: Bool
{
public var playing: Bool {
return self.player.rate > 0
}
public var error: NSError?
{
public var error: NSError? {
return self.player.errorForPlayerOrItem
}
public func seek(to time: TimeInterval)
{
let cmTime = CMTimeMakeWithSeconds(time, Int32(NSEC_PER_SEC))
public func seek(to time: TimeInterval) {
let cmTime = CMTimeMakeWithSeconds(time, preferredTimescale: Int32(NSEC_PER_SEC))
self.player.seek(to: cmTime)
self.time = time
}
public func play()
{
public func play() {
self.player.play()
}
public func pause()
{
public func pause() {
self.player.pause()
}
// MARK: Lifecycle
public override init()
{
public override init() {
super.init()
self.addPlayerObservers()
@@ -153,10 +136,8 @@ open class RegularPlayer: NSObject, Player, ProvidesView
self.setupAirplay()
}
deinit
{
if let playerItem = self.player.currentItem
{
deinit {
if let playerItem = self.player.currentItem {
self.removePlayerItemObservers(fromPlayerItem: playerItem)
}
@@ -165,22 +146,18 @@ open class RegularPlayer: NSObject, Player, ProvidesView
// MARK: Setup
private func setupAirplay()
{
private func setupAirplay() {
self.player.usesExternalPlaybackWhileExternalScreenIsActive = true
}
// MARK: Observers
private struct KeyPath
{
struct Player
{
private struct KeyPath {
struct Player {
static let Rate = "rate"
}
struct PlayerItem
{
struct PlayerItem {
static let Status = "status"
static let PlaybackLikelyToKeepUp = "playbackLikelyToKeepUp"
static let LoadedTimeRanges = "loadedTimeRanges"
@@ -189,41 +166,35 @@ open class RegularPlayer: NSObject, Player, ProvidesView
private var playerTimeObserver: Any?
private func addPlayerItemObservers(toPlayerItem playerItem: AVPlayerItem)
{
private func addPlayerItemObservers(toPlayerItem playerItem: AVPlayerItem) {
playerItem.addObserver(self, forKeyPath: KeyPath.PlayerItem.Status, options: [.initial, .new], context: nil)
playerItem.addObserver(self, forKeyPath: KeyPath.PlayerItem.PlaybackLikelyToKeepUp, options: [.initial, .new], context: nil)
playerItem.addObserver(self, forKeyPath: KeyPath.PlayerItem.LoadedTimeRanges, options: [.initial, .new], context: nil)
}
private func removePlayerItemObservers(fromPlayerItem playerItem: AVPlayerItem)
{
private func removePlayerItemObservers(fromPlayerItem playerItem: AVPlayerItem) {
playerItem.removeObserver(self, forKeyPath: KeyPath.PlayerItem.Status, context: nil)
playerItem.removeObserver(self, forKeyPath: KeyPath.PlayerItem.PlaybackLikelyToKeepUp, context: nil)
playerItem.removeObserver(self, forKeyPath: KeyPath.PlayerItem.LoadedTimeRanges, context: nil)
}
private func addPlayerObservers()
{
private func addPlayerObservers() {
self.player.addObserver(self, forKeyPath: KeyPath.Player.Rate, options: [.initial, .new], context: nil)
let interval = CMTimeMakeWithSeconds(Constants.TimeUpdateInterval, Int32(NSEC_PER_SEC))
let interval = CMTimeMakeWithSeconds(Constants.TimeUpdateInterval, preferredTimescale: Int32(NSEC_PER_SEC))
self.playerTimeObserver = self.player.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: { [weak self] (cmTime) in
if let strongSelf = self, let time = cmTime.timeInterval
{
if let strongSelf = self, let time = cmTime.timeInterval {
strongSelf.time = time
}
})
}
private func removePlayerObservers()
{
private func removePlayerObservers() {
self.player.removeObserver(self, forKeyPath: KeyPath.Player.Rate, context: nil)
if let playerTimeObserver = self.playerTimeObserver
{
if let playerTimeObserver = self.playerTimeObserver {
self.player.removeTimeObserver(playerTimeObserver)
self.playerTimeObserver = nil
@@ -232,56 +203,44 @@ open class RegularPlayer: NSObject, Player, ProvidesView
// MARK: Observation
override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{
override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
// Player Item Observers
if keyPath == KeyPath.PlayerItem.Status
{
if let statusInt = change?[.newKey] as? Int, let status = AVPlayerItemStatus(rawValue: statusInt)
{
if keyPath == KeyPath.PlayerItem.Status {
if let statusInt = change?[.newKey] as? Int, let status = AVPlayerItem.Status(rawValue: statusInt) {
self.playerItemStatusDidChange(status: status)
}
}
else if keyPath == KeyPath.PlayerItem.PlaybackLikelyToKeepUp
{
if let playbackLikelyToKeepUp = change?[.newKey] as? Bool
{
else if keyPath == KeyPath.PlayerItem.PlaybackLikelyToKeepUp {
if let playbackLikelyToKeepUp = change?[.newKey] as? Bool {
self.playerItemPlaybackLikelyToKeepUpDidChange(playbackLikelyToKeepUp: playbackLikelyToKeepUp)
}
}
else if keyPath == KeyPath.PlayerItem.LoadedTimeRanges
{
if let loadedTimeRanges = change?[.newKey] as? [NSValue]
{
else if keyPath == KeyPath.PlayerItem.LoadedTimeRanges {
if let loadedTimeRanges = change?[.newKey] as? [NSValue] {
self.playerItemLoadedTimeRangesDidChange(loadedTimeRanges: loadedTimeRanges)
}
}
// Player Observers
else if keyPath == KeyPath.Player.Rate
{
if let rate = change?[.newKey] as? Float
{
else if keyPath == KeyPath.Player.Rate {
if let rate = change?[.newKey] as? Float {
self.playerRateDidChange(rate: rate)
}
}
// Fall Through Observers
else
{
else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
// MARK: Observation Helpers
private func playerItemStatusDidChange(status: AVPlayerItemStatus)
{
switch status
{
private func playerItemStatusDidChange(status: AVPlayerItem.Status) {
switch status {
case .unknown:
self.state = .loading
@@ -296,22 +255,18 @@ open class RegularPlayer: NSObject, Player, ProvidesView
}
}
private func playerRateDidChange(rate: Float)
{
private func playerRateDidChange(rate: Float) {
self.delegate?.playerDidUpdatePlaying(player: self)
}
private func playerItemPlaybackLikelyToKeepUpDidChange(playbackLikelyToKeepUp: Bool)
{
private func playerItemPlaybackLikelyToKeepUpDidChange(playbackLikelyToKeepUp: Bool) {
let state: PlayerState = playbackLikelyToKeepUp ? .ready : .loading
self.state = state
}
private func playerItemLoadedTimeRangesDidChange(loadedTimeRanges: [NSValue])
{
guard let bufferedCMTime = loadedTimeRanges.first?.timeRangeValue.end, let bufferedTime = bufferedCMTime.timeInterval else
{
private func playerItemLoadedTimeRangesDidChange(loadedTimeRanges: [NSValue]) {
guard let bufferedCMTime = loadedTimeRanges.first?.timeRangeValue.end, let bufferedTime = bufferedCMTime.timeInterval else {
return
}
@@ -332,25 +287,20 @@ open class RegularPlayer: NSObject, Player, ProvidesView
extension RegularPlayer: AirPlayCapable
{
public var isAirPlayEnabled: Bool
{
get
{
public var isAirPlayEnabled: Bool {
get {
return self.player.allowsExternalPlayback
}
set
{
set {
return self.player.allowsExternalPlayback = newValue
}
}
}
#if os(iOS)
extension RegularPlayer: PictureInPictureCapable
{
extension RegularPlayer: PictureInPictureCapable {
@available(iOS 9.0, *)
public var pictureInPictureController: AVPictureInPictureController?
{
public var pictureInPictureController: AVPictureInPictureController? {
return self._pictureInPictureController
}
}
@@ -358,30 +308,90 @@ extension RegularPlayer: PictureInPictureCapable
extension RegularPlayer: VolumeCapable
{
public var volume: Float
{
get
{
public var volume: Float {
get {
return self.player.volume
}
set
{
set {
self.player.volume = newValue
}
}
}
extension RegularPlayer: FillModeCapable
{
public var fillMode: String
{
get
{
return (self.view.layer as! AVPlayerLayer).videoGravity
extension RegularPlayer: FillModeCapable {
public var fillMode: FillMode {
get {
let gravity = (self.view.layer as! AVPlayerLayer).videoGravity
return gravity == .resizeAspect ? .fit : .fill
}
set
{
(self.view.layer as! AVPlayerLayer).videoGravity = newValue
set {
let gravity: AVLayerVideoGravity
switch newValue {
case .fit:
gravity = .resizeAspect
case .fill:
gravity = .resizeAspectFill
}
(self.view.layer as! AVPlayerLayer).videoGravity = gravity
}
}
}
extension RegularPlayer: TextTrackCapable {
public var selectedTextTrack: TextTrackMetadata? {
guard let group = self.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
return nil
}
if #available(iOS 9.0, *) {
return self.player.currentItem?.currentMediaSelection.selectedMediaOption(in: group)
}
else {
return self.player.currentItem?.selectedMediaOption(in: group)
}
}
public var availableTextTracks: [TextTrackMetadata] {
guard let group = self.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
return []
}
return group.options
}
public func fetchTextTracks(completion: @escaping ([TextTrackMetadata], TextTrackMetadata?) -> Void) {
self.player.currentItem?.asset.loadValuesAsynchronously(forKeys: [#keyPath(AVAsset.availableMediaCharacteristicsWithMediaSelectionOptions)]) { [weak self] in
guard let strongSelf = self, let group = strongSelf.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
completion([], nil)
return
}
if #available(iOS 9.0, *) {
completion(group.options, strongSelf.player.currentItem?.currentMediaSelection.selectedMediaOption(in: group))
}
else {
completion(group.options, strongSelf.player.currentItem?.selectedMediaOption(in: group))
}
}
}
public func select(_ textTrack: TextTrackMetadata?) {
guard let group = self.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
return
}
guard let track = textTrack else {
self.player.currentItem?.select(nil, in: group)
return
}
let option = group.options.first(where: { option in
track.matches(option)
})
self.player.currentItem?.select(option, in: group)
}
}
+6 -6
View File
@@ -1,6 +1,6 @@
# PlayerKit
[![CI Status](http://img.shields.io/travis/ghking/PlayerKit.svg?style=flat)](https://travis-ci.org/ghking/PlayerKit)
[![CI Status](http://img.shields.io/travis/ghking/PlayerKit.svg?style=flat)](https://travis-ci.org/vimeo/PlayerKit)
[![Version](https://img.shields.io/cocoapods/v/PlayerKit.svg?style=flat)](http://cocoapods.org/pods/PlayerKit)
[![License](https://img.shields.io/cocoapods/l/PlayerKit.svg?style=flat)](http://cocoapods.org/pods/PlayerKit)
[![Platform](https://img.shields.io/cocoapods/p/PlayerKit.svg?style=flat)](http://cocoapods.org/pods/PlayerKit)
@@ -20,10 +20,10 @@ Vimeo supports various types of video and playback (360 video, Chromecast, etc.)
To run the example project, clone the repo, and run `pod install` from the Example directory.
## Requirements
## Minimum Requirements
- iOS 8.0+ / tvOS 9.0+
- Swift 3.2
- iOS 8.0 / tvOS 9.0
- Swift 4.2
## Installation
@@ -62,9 +62,9 @@ player.delegate = delegate
You can create your own players by creating objects that conform to the Player protocol and call the delegate methods when appropriate.
## Author
## Questions?
Gavin King, gavin@vimeo.com
Post on [Stackoverflow](http://stackoverflow.com/questions/tagged/vimeo-ios) with the tag `vimeo-ios`. Get in touch [here](https://vimeo.com/help/contact). Interested in working at Vimeo? We're [hiring](https://vimeo.com/jobs)!
## License
-1
View File
@@ -1 +0,0 @@
Example/Pods/Pods.xcodeproj
-19
View File
@@ -1,19 +0,0 @@
general:
artifacts:
- "build/Logs"
- "PlayerKit_Example-PlayerKit-Example.log"
machine:
xcode:
version: 9.0
dependencies:
override:
- bundle install --deployment
cache_directories:
- "~/.cocoapods"
- "Example/Pods"
- "vendor/bundle"
test:
override:
- bundle exec fastlane test
+23 -2
View File
@@ -17,10 +17,10 @@ default_platform :ios
platform :ios do
before_all do
ensure_xcode_version(version: "9.0")
ensure_xcode_version(version: "10.1")
end
desc "run tests"
desc "Run tests"
lane :test do |options|
cocoapods(
@@ -43,6 +43,27 @@ platform :ios do
end
end
desc "bumps the project and podspec version"
lane :version_bump do |options|
bump_type = options[:bump_type]
version_number = options[:version_number]
if bump_type.nil? && version_number.nil?
UI.user_error!("version_bump requires you to provide a bump_type [patch|minor|major] or specific version_number. Please try again.")
end
increment_version_number(
bump_type: bump_type,
version_number: version_number,
xcodeproj: "Example/PlayerKit.xcodeproj"
)
version_bump_podspec(
bump_type: bump_type,
version_number: version_number
)
end
after_all do |lane|
end
+7 -1
View File
@@ -27,13 +27,19 @@ xcode-select --install
<td width="33%"><code>sudo gem install fastlane -NV</code></td>
</tr>
</table>
# Available Actions
## iOS
### ios test
```
fastlane ios test
```
run tests
Run tests
### ios version_bump
```
fastlane ios version_bump
```
bumps the project and podspec version
----