├── .gitignore ├── Demo ├── ObjC │ ├── PiP Client.xcodeproj │ │ └── project.pbxproj │ └── PiP Client │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── PlayerViewController.h │ │ ├── PlayerViewController.m │ │ └── main.m └── Swift │ ├── PiP Client.xcodeproj │ └── project.pbxproj │ └── PiP Client │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ └── Main.storyboard │ ├── Info.plist │ └── PlayerViewController.swift ├── Framework ├── Info.plist └── PIPContainer.h ├── LICENSE ├── PIPContainer.podspec ├── PIPContainer.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ └── PIPContainer.xcscheme ├── README.md ├── Screenshots ├── containment.png ├── embedded-binaries.png └── pipdemo.gif └── Sources ├── PIPContainerViewController.h ├── PIPContainerViewController.m └── Private └── PIP.h /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | __MACOSX 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | DerivedData 17 | .idea/ 18 | Crashlytics.sh 19 | generatechangelog.sh 20 | Pods/ -------------------------------------------------------------------------------- /Demo/ObjC/PiP Client.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | DD34E36E1DC6C4CB004324E6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DD34E36D1DC6C4CB004324E6 /* AppDelegate.m */; }; 11 | DD34E3711DC6C4CB004324E6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DD34E3701DC6C4CB004324E6 /* main.m */; }; 12 | DD34E3761DC6C4CB004324E6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD34E3751DC6C4CB004324E6 /* Assets.xcassets */; }; 13 | DD34E3791DC6C4CB004324E6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DD34E3771DC6C4CB004324E6 /* Main.storyboard */; }; 14 | DD9F19611E11204B007110C4 /* PlayerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9F19601E11204B007110C4 /* PlayerViewController.m */; }; 15 | DD9F19C31E112E90007110C4 /* PIPContainer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD9F19C21E112E8B007110C4 /* PIPContainer.framework */; }; 16 | DD9F19C41E112E90007110C4 /* PIPContainer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DD9F19C21E112E8B007110C4 /* PIPContainer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | DD9F19C11E112E8B007110C4 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = DD9F19BD1E112E8B007110C4 /* PIPContainer.xcodeproj */; 23 | proxyType = 2; 24 | remoteGlobalIDString = DD9F196C1E112A3E007110C4; 25 | remoteInfo = PIPContainer; 26 | }; 27 | DD9F19C51E112E90007110C4 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = DD9F19BD1E112E8B007110C4 /* PIPContainer.xcodeproj */; 30 | proxyType = 1; 31 | remoteGlobalIDString = DD9F196B1E112A3E007110C4; 32 | remoteInfo = PIPContainer; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXCopyFilesBuildPhase section */ 37 | DD9F19911E112B54007110C4 /* Embed Frameworks */ = { 38 | isa = PBXCopyFilesBuildPhase; 39 | buildActionMask = 2147483647; 40 | dstPath = ""; 41 | dstSubfolderSpec = 10; 42 | files = ( 43 | DD9F19C41E112E90007110C4 /* PIPContainer.framework in Embed Frameworks */, 44 | ); 45 | name = "Embed Frameworks"; 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXCopyFilesBuildPhase section */ 49 | 50 | /* Begin PBXFileReference section */ 51 | DD34E3691DC6C4CB004324E6 /* PiP Client.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "PiP Client.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | DD34E36C1DC6C4CB004324E6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 53 | DD34E36D1DC6C4CB004324E6 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 54 | DD34E3701DC6C4CB004324E6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 55 | DD34E3751DC6C4CB004324E6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 56 | DD34E3781DC6C4CB004324E6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 57 | DD34E37A1DC6C4CB004324E6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | DD34E3811DC6C4D3004324E6 /* PIP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PIP.framework; path = ../../../../../../System/Library/PrivateFrameworks/PIP.framework; sourceTree = ""; }; 59 | DD9F195F1E11204B007110C4 /* PlayerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayerViewController.h; sourceTree = ""; }; 60 | DD9F19601E11204B007110C4 /* PlayerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlayerViewController.m; sourceTree = ""; }; 61 | DD9F19BD1E112E8B007110C4 /* PIPContainer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = PIPContainer.xcodeproj; path = ../../PIPContainer.xcodeproj; sourceTree = ""; }; 62 | /* End PBXFileReference section */ 63 | 64 | /* Begin PBXFrameworksBuildPhase section */ 65 | DD34E3661DC6C4CB004324E6 /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | DD9F19C31E112E90007110C4 /* PIPContainer.framework in Frameworks */, 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | /* End PBXFrameworksBuildPhase section */ 74 | 75 | /* Begin PBXGroup section */ 76 | DD34E3601DC6C4CB004324E6 = { 77 | isa = PBXGroup; 78 | children = ( 79 | DD9F19BD1E112E8B007110C4 /* PIPContainer.xcodeproj */, 80 | DD34E36B1DC6C4CB004324E6 /* PiP Client */, 81 | DD34E36A1DC6C4CB004324E6 /* Products */, 82 | DD34E3801DC6C4D3004324E6 /* Frameworks */, 83 | ); 84 | sourceTree = ""; 85 | }; 86 | DD34E36A1DC6C4CB004324E6 /* Products */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | DD34E3691DC6C4CB004324E6 /* PiP Client.app */, 90 | ); 91 | name = Products; 92 | sourceTree = ""; 93 | }; 94 | DD34E36B1DC6C4CB004324E6 /* PiP Client */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | DD9F195E1E112031007110C4 /* Resources */, 98 | DD9F195D1E111F9A007110C4 /* Bootstrap */, 99 | DD9F195C1E111F95007110C4 /* Controllers */, 100 | DD34E36F1DC6C4CB004324E6 /* Supporting Files */, 101 | ); 102 | path = "PiP Client"; 103 | sourceTree = ""; 104 | }; 105 | DD34E36F1DC6C4CB004324E6 /* Supporting Files */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | DD34E3701DC6C4CB004324E6 /* main.m */, 109 | ); 110 | name = "Supporting Files"; 111 | sourceTree = ""; 112 | }; 113 | DD34E3801DC6C4D3004324E6 /* Frameworks */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | DD34E3811DC6C4D3004324E6 /* PIP.framework */, 117 | ); 118 | name = Frameworks; 119 | sourceTree = ""; 120 | }; 121 | DD9F195C1E111F95007110C4 /* Controllers */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | DD9F195F1E11204B007110C4 /* PlayerViewController.h */, 125 | DD9F19601E11204B007110C4 /* PlayerViewController.m */, 126 | ); 127 | name = Controllers; 128 | sourceTree = ""; 129 | }; 130 | DD9F195D1E111F9A007110C4 /* Bootstrap */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | DD34E36C1DC6C4CB004324E6 /* AppDelegate.h */, 134 | DD34E36D1DC6C4CB004324E6 /* AppDelegate.m */, 135 | ); 136 | name = Bootstrap; 137 | sourceTree = ""; 138 | }; 139 | DD9F195E1E112031007110C4 /* Resources */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | DD34E3751DC6C4CB004324E6 /* Assets.xcassets */, 143 | DD34E3771DC6C4CB004324E6 /* Main.storyboard */, 144 | DD34E37A1DC6C4CB004324E6 /* Info.plist */, 145 | ); 146 | name = Resources; 147 | sourceTree = ""; 148 | }; 149 | DD9F19BE1E112E8B007110C4 /* Products */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | DD9F19C21E112E8B007110C4 /* PIPContainer.framework */, 153 | ); 154 | name = Products; 155 | sourceTree = ""; 156 | }; 157 | /* End PBXGroup section */ 158 | 159 | /* Begin PBXNativeTarget section */ 160 | DD34E3681DC6C4CB004324E6 /* PiP Client */ = { 161 | isa = PBXNativeTarget; 162 | buildConfigurationList = DD34E37D1DC6C4CB004324E6 /* Build configuration list for PBXNativeTarget "PiP Client" */; 163 | buildPhases = ( 164 | DD34E3651DC6C4CB004324E6 /* Sources */, 165 | DD34E3661DC6C4CB004324E6 /* Frameworks */, 166 | DD34E3671DC6C4CB004324E6 /* Resources */, 167 | DD9F19911E112B54007110C4 /* Embed Frameworks */, 168 | ); 169 | buildRules = ( 170 | ); 171 | dependencies = ( 172 | DD9F19C61E112E90007110C4 /* PBXTargetDependency */, 173 | ); 174 | name = "PiP Client"; 175 | productName = "PiP Client"; 176 | productReference = DD34E3691DC6C4CB004324E6 /* PiP Client.app */; 177 | productType = "com.apple.product-type.application"; 178 | }; 179 | /* End PBXNativeTarget section */ 180 | 181 | /* Begin PBXProject section */ 182 | DD34E3611DC6C4CB004324E6 /* Project object */ = { 183 | isa = PBXProject; 184 | attributes = { 185 | LastUpgradeCheck = 0810; 186 | ORGANIZATIONNAME = "Guilherme Rambo"; 187 | TargetAttributes = { 188 | DD34E3681DC6C4CB004324E6 = { 189 | CreatedOnToolsVersion = 8.1; 190 | DevelopmentTeam = 8C7439RJLG; 191 | ProvisioningStyle = Automatic; 192 | }; 193 | }; 194 | }; 195 | buildConfigurationList = DD34E3641DC6C4CB004324E6 /* Build configuration list for PBXProject "PiP Client" */; 196 | compatibilityVersion = "Xcode 3.2"; 197 | developmentRegion = English; 198 | hasScannedForEncodings = 0; 199 | knownRegions = ( 200 | en, 201 | Base, 202 | ); 203 | mainGroup = DD34E3601DC6C4CB004324E6; 204 | productRefGroup = DD34E36A1DC6C4CB004324E6 /* Products */; 205 | projectDirPath = ""; 206 | projectReferences = ( 207 | { 208 | ProductGroup = DD9F19BE1E112E8B007110C4 /* Products */; 209 | ProjectRef = DD9F19BD1E112E8B007110C4 /* PIPContainer.xcodeproj */; 210 | }, 211 | ); 212 | projectRoot = ""; 213 | targets = ( 214 | DD34E3681DC6C4CB004324E6 /* PiP Client */, 215 | ); 216 | }; 217 | /* End PBXProject section */ 218 | 219 | /* Begin PBXReferenceProxy section */ 220 | DD9F19C21E112E8B007110C4 /* PIPContainer.framework */ = { 221 | isa = PBXReferenceProxy; 222 | fileType = wrapper.framework; 223 | path = PIPContainer.framework; 224 | remoteRef = DD9F19C11E112E8B007110C4 /* PBXContainerItemProxy */; 225 | sourceTree = BUILT_PRODUCTS_DIR; 226 | }; 227 | /* End PBXReferenceProxy section */ 228 | 229 | /* Begin PBXResourcesBuildPhase section */ 230 | DD34E3671DC6C4CB004324E6 /* Resources */ = { 231 | isa = PBXResourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | DD34E3761DC6C4CB004324E6 /* Assets.xcassets in Resources */, 235 | DD34E3791DC6C4CB004324E6 /* Main.storyboard in Resources */, 236 | ); 237 | runOnlyForDeploymentPostprocessing = 0; 238 | }; 239 | /* End PBXResourcesBuildPhase section */ 240 | 241 | /* Begin PBXSourcesBuildPhase section */ 242 | DD34E3651DC6C4CB004324E6 /* Sources */ = { 243 | isa = PBXSourcesBuildPhase; 244 | buildActionMask = 2147483647; 245 | files = ( 246 | DD9F19611E11204B007110C4 /* PlayerViewController.m in Sources */, 247 | DD34E3711DC6C4CB004324E6 /* main.m in Sources */, 248 | DD34E36E1DC6C4CB004324E6 /* AppDelegate.m in Sources */, 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | }; 252 | /* End PBXSourcesBuildPhase section */ 253 | 254 | /* Begin PBXTargetDependency section */ 255 | DD9F19C61E112E90007110C4 /* PBXTargetDependency */ = { 256 | isa = PBXTargetDependency; 257 | name = PIPContainer; 258 | targetProxy = DD9F19C51E112E90007110C4 /* PBXContainerItemProxy */; 259 | }; 260 | /* End PBXTargetDependency section */ 261 | 262 | /* Begin PBXVariantGroup section */ 263 | DD34E3771DC6C4CB004324E6 /* Main.storyboard */ = { 264 | isa = PBXVariantGroup; 265 | children = ( 266 | DD34E3781DC6C4CB004324E6 /* Base */, 267 | ); 268 | name = Main.storyboard; 269 | sourceTree = ""; 270 | }; 271 | /* End PBXVariantGroup section */ 272 | 273 | /* Begin XCBuildConfiguration section */ 274 | DD34E37B1DC6C4CB004324E6 /* Debug */ = { 275 | isa = XCBuildConfiguration; 276 | buildSettings = { 277 | ALWAYS_SEARCH_USER_PATHS = NO; 278 | CLANG_ANALYZER_NONNULL = YES; 279 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 280 | CLANG_CXX_LIBRARY = "libc++"; 281 | CLANG_ENABLE_MODULES = YES; 282 | CLANG_ENABLE_OBJC_ARC = YES; 283 | CLANG_WARN_BOOL_CONVERSION = YES; 284 | CLANG_WARN_CONSTANT_CONVERSION = YES; 285 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 286 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 287 | CLANG_WARN_EMPTY_BODY = YES; 288 | CLANG_WARN_ENUM_CONVERSION = YES; 289 | CLANG_WARN_INFINITE_RECURSION = YES; 290 | CLANG_WARN_INT_CONVERSION = YES; 291 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 292 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 293 | CLANG_WARN_UNREACHABLE_CODE = YES; 294 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 295 | CODE_SIGN_IDENTITY = "-"; 296 | COPY_PHASE_STRIP = NO; 297 | DEBUG_INFORMATION_FORMAT = dwarf; 298 | ENABLE_STRICT_OBJC_MSGSEND = YES; 299 | ENABLE_TESTABILITY = YES; 300 | GCC_C_LANGUAGE_STANDARD = gnu99; 301 | GCC_DYNAMIC_NO_PIC = NO; 302 | GCC_NO_COMMON_BLOCKS = YES; 303 | GCC_OPTIMIZATION_LEVEL = 0; 304 | GCC_PREPROCESSOR_DEFINITIONS = ( 305 | "DEBUG=1", 306 | "$(inherited)", 307 | ); 308 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 309 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 310 | GCC_WARN_UNDECLARED_SELECTOR = YES; 311 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 312 | GCC_WARN_UNUSED_FUNCTION = YES; 313 | GCC_WARN_UNUSED_VARIABLE = YES; 314 | MACOSX_DEPLOYMENT_TARGET = 10.12; 315 | MTL_ENABLE_DEBUG_INFO = YES; 316 | ONLY_ACTIVE_ARCH = YES; 317 | SDKROOT = macosx; 318 | }; 319 | name = Debug; 320 | }; 321 | DD34E37C1DC6C4CB004324E6 /* Release */ = { 322 | isa = XCBuildConfiguration; 323 | buildSettings = { 324 | ALWAYS_SEARCH_USER_PATHS = NO; 325 | CLANG_ANALYZER_NONNULL = YES; 326 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 327 | CLANG_CXX_LIBRARY = "libc++"; 328 | CLANG_ENABLE_MODULES = YES; 329 | CLANG_ENABLE_OBJC_ARC = YES; 330 | CLANG_WARN_BOOL_CONVERSION = YES; 331 | CLANG_WARN_CONSTANT_CONVERSION = YES; 332 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 333 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 334 | CLANG_WARN_EMPTY_BODY = YES; 335 | CLANG_WARN_ENUM_CONVERSION = YES; 336 | CLANG_WARN_INFINITE_RECURSION = YES; 337 | CLANG_WARN_INT_CONVERSION = YES; 338 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 339 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 340 | CLANG_WARN_UNREACHABLE_CODE = YES; 341 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 342 | CODE_SIGN_IDENTITY = "-"; 343 | COPY_PHASE_STRIP = NO; 344 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 345 | ENABLE_NS_ASSERTIONS = NO; 346 | ENABLE_STRICT_OBJC_MSGSEND = YES; 347 | GCC_C_LANGUAGE_STANDARD = gnu99; 348 | GCC_NO_COMMON_BLOCKS = YES; 349 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 350 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 351 | GCC_WARN_UNDECLARED_SELECTOR = YES; 352 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 353 | GCC_WARN_UNUSED_FUNCTION = YES; 354 | GCC_WARN_UNUSED_VARIABLE = YES; 355 | MACOSX_DEPLOYMENT_TARGET = 10.12; 356 | MTL_ENABLE_DEBUG_INFO = NO; 357 | SDKROOT = macosx; 358 | }; 359 | name = Release; 360 | }; 361 | DD34E37E1DC6C4CB004324E6 /* Debug */ = { 362 | isa = XCBuildConfiguration; 363 | buildSettings = { 364 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 365 | COMBINE_HIDPI_IMAGES = YES; 366 | DEVELOPMENT_TEAM = 8C7439RJLG; 367 | FRAMEWORK_SEARCH_PATHS = ( 368 | "$(inherited)", 369 | "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", 370 | ); 371 | INFOPLIST_FILE = "PiP Client/Info.plist"; 372 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 373 | PRODUCT_BUNDLE_IDENTIFIER = "br.com.guilhermerambo.PiP-Client"; 374 | PRODUCT_NAME = "$(TARGET_NAME)"; 375 | }; 376 | name = Debug; 377 | }; 378 | DD34E37F1DC6C4CB004324E6 /* Release */ = { 379 | isa = XCBuildConfiguration; 380 | buildSettings = { 381 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 382 | COMBINE_HIDPI_IMAGES = YES; 383 | DEVELOPMENT_TEAM = 8C7439RJLG; 384 | FRAMEWORK_SEARCH_PATHS = ( 385 | "$(inherited)", 386 | "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", 387 | ); 388 | INFOPLIST_FILE = "PiP Client/Info.plist"; 389 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 390 | PRODUCT_BUNDLE_IDENTIFIER = "br.com.guilhermerambo.PiP-Client"; 391 | PRODUCT_NAME = "$(TARGET_NAME)"; 392 | }; 393 | name = Release; 394 | }; 395 | /* End XCBuildConfiguration section */ 396 | 397 | /* Begin XCConfigurationList section */ 398 | DD34E3641DC6C4CB004324E6 /* Build configuration list for PBXProject "PiP Client" */ = { 399 | isa = XCConfigurationList; 400 | buildConfigurations = ( 401 | DD34E37B1DC6C4CB004324E6 /* Debug */, 402 | DD34E37C1DC6C4CB004324E6 /* Release */, 403 | ); 404 | defaultConfigurationIsVisible = 0; 405 | defaultConfigurationName = Release; 406 | }; 407 | DD34E37D1DC6C4CB004324E6 /* Build configuration list for PBXNativeTarget "PiP Client" */ = { 408 | isa = XCConfigurationList; 409 | buildConfigurations = ( 410 | DD34E37E1DC6C4CB004324E6 /* Debug */, 411 | DD34E37F1DC6C4CB004324E6 /* Release */, 412 | ); 413 | defaultConfigurationIsVisible = 0; 414 | defaultConfigurationName = Release; 415 | }; 416 | /* End XCConfigurationList section */ 417 | }; 418 | rootObject = DD34E3611DC6C4CB004324E6 /* Project object */; 419 | } 420 | -------------------------------------------------------------------------------- /Demo/ObjC/PiP Client/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PiP Client 4 | // 5 | // Created by Guilherme Rambo on 30/10/16. 6 | // Copyright © 2016 Guilherme Rambo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Demo/ObjC/PiP Client/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PiP Client 4 | // 5 | // Created by Guilherme Rambo on 30/10/16. 6 | // Copyright © 2016 Guilherme Rambo. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 18 | // Insert code here to initialize your application 19 | } 20 | 21 | 22 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 23 | // Insert code here to tear down your application 24 | } 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Demo/ObjC/PiP Client/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /Demo/ObjC/PiP Client/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | Default 511 | 512 | 513 | 514 | 515 | 516 | 517 | Left to Right 518 | 519 | 520 | 521 | 522 | 523 | 524 | Right to Left 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | Default 536 | 537 | 538 | 539 | 540 | 541 | 542 | Left to Right 543 | 544 | 545 | 546 | 547 | 548 | 549 | Right to Left 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | -------------------------------------------------------------------------------- /Demo/ObjC/PiP Client/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2016 Guilherme Rambo. All rights reserved. 27 | NSMainStoryboardFile 28 | Main 29 | NSPrincipalClass 30 | NSApplication 31 | NSAppTransportSecurity 32 | 33 | NSAllowsArbitraryLoads 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Demo/ObjC/PiP Client/PlayerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayerViewController.h 3 | // PiP Client 4 | // 5 | // Created by Guilherme Rambo on 26/12/16. 6 | // Copyright © 2016 Guilherme Rambo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PlayerViewController : NSViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Demo/ObjC/PiP Client/PlayerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlayerViewController.m 3 | // PiP Client 4 | // 5 | // Created by Guilherme Rambo on 26/12/16. 6 | // Copyright © 2016 Guilherme Rambo. All rights reserved. 7 | // 8 | 9 | #import "PlayerViewController.h" 10 | 11 | @import PIPContainer; 12 | 13 | @import AVFoundation; 14 | 15 | @interface PlayerViewController () 16 | 17 | @property (strong) AVPlayer *player; 18 | 19 | @end 20 | 21 | @implementation PlayerViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | 26 | self.player = [AVPlayer playerWithURL:[NSURL URLWithString:@"http://p.events-delivery.apple.com.edgesuite.net/16oibfvohbfvoihbdfvoihbefv10/m3u8/atv_vod_mvp.m3u8"]]; 27 | self.view.layer = [AVPlayerLayer playerLayerWithPlayer:self.player]; 28 | self.view.layer.backgroundColor = [NSColor blackColor].CGColor; 29 | [self.player seekToTime:CMTimeMakeWithSeconds(912, NSEC_PER_SEC)]; 30 | [self.player play]; 31 | } 32 | 33 | - (void)viewDidAppear 34 | { 35 | [super viewDidAppear]; 36 | 37 | self.view.window.titleVisibility = NSWindowTitleHidden; 38 | 39 | [self setupPIPSupport]; 40 | } 41 | 42 | - (void)setupPIPSupport 43 | { 44 | if (![self.parentViewController isKindOfClass:[PIPContainerViewController class]]) return; 45 | 46 | __weak PIPContainerViewController *pipContainer = (PIPContainerViewController *)self.parentViewController; 47 | 48 | __weak typeof(self) welf = self; 49 | 50 | [pipContainer setPipWillOpen:^{ 51 | [pipContainer setPlaying:(self.player.rate != 0)]; 52 | }]; 53 | 54 | [pipContainer setPipDidPlay:^{ 55 | [welf.player play]; 56 | }]; 57 | 58 | [pipContainer setPipDidPause:^{ 59 | [welf.player pause]; 60 | }]; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Demo/ObjC/PiP Client/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PiP Client 4 | // 5 | // Created by Guilherme Rambo on 30/10/16. 6 | // Copyright © 2016 Guilherme Rambo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /Demo/Swift/PiP Client.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | DD9F199F1E112BCA007110C4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9F199E1E112BCA007110C4 /* AppDelegate.swift */; }; 11 | DD9F19A11E112BCA007110C4 /* PlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9F19A01E112BCA007110C4 /* PlayerViewController.swift */; }; 12 | DD9F19A31E112BCA007110C4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD9F19A21E112BCA007110C4 /* Assets.xcassets */; }; 13 | DD9F19A61E112BCA007110C4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DD9F19A41E112BCA007110C4 /* Main.storyboard */; }; 14 | DD9F19CE1E112EB2007110C4 /* PIPContainer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD9F19CD1E112EB0007110C4 /* PIPContainer.framework */; }; 15 | DD9F19CF1E112EB2007110C4 /* PIPContainer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DD9F19CD1E112EB0007110C4 /* PIPContainer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | DD9F19CC1E112EB0007110C4 /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = DD9F19C81E112EAF007110C4 /* PIPContainer.xcodeproj */; 22 | proxyType = 2; 23 | remoteGlobalIDString = DD9F196C1E112A3E007110C4; 24 | remoteInfo = PIPContainer; 25 | }; 26 | DD9F19D01E112EB2007110C4 /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = DD9F19C81E112EAF007110C4 /* PIPContainer.xcodeproj */; 29 | proxyType = 1; 30 | remoteGlobalIDString = DD9F196B1E112A3E007110C4; 31 | remoteInfo = PIPContainer; 32 | }; 33 | /* End PBXContainerItemProxy section */ 34 | 35 | /* Begin PBXCopyFilesBuildPhase section */ 36 | DD9F19BA1E112C0B007110C4 /* Embed Frameworks */ = { 37 | isa = PBXCopyFilesBuildPhase; 38 | buildActionMask = 2147483647; 39 | dstPath = ""; 40 | dstSubfolderSpec = 10; 41 | files = ( 42 | DD9F19CF1E112EB2007110C4 /* PIPContainer.framework in Embed Frameworks */, 43 | ); 44 | name = "Embed Frameworks"; 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | /* End PBXCopyFilesBuildPhase section */ 48 | 49 | /* Begin PBXFileReference section */ 50 | DD9F199B1E112BCA007110C4 /* PiP Client.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "PiP Client.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | DD9F199E1E112BCA007110C4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 52 | DD9F19A01E112BCA007110C4 /* PlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerViewController.swift; sourceTree = ""; }; 53 | DD9F19A21E112BCA007110C4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | DD9F19A51E112BCA007110C4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 55 | DD9F19A71E112BCA007110C4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | DD9F19C81E112EAF007110C4 /* PIPContainer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = PIPContainer.xcodeproj; path = ../../PIPContainer.xcodeproj; sourceTree = ""; }; 57 | /* End PBXFileReference section */ 58 | 59 | /* Begin PBXFrameworksBuildPhase section */ 60 | DD9F19981E112BCA007110C4 /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | DD9F19CE1E112EB2007110C4 /* PIPContainer.framework in Frameworks */, 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | DD9F19921E112BCA007110C4 = { 72 | isa = PBXGroup; 73 | children = ( 74 | DD9F19C81E112EAF007110C4 /* PIPContainer.xcodeproj */, 75 | DD9F199D1E112BCA007110C4 /* PiP Client */, 76 | DD9F199C1E112BCA007110C4 /* Products */, 77 | ); 78 | sourceTree = ""; 79 | }; 80 | DD9F199C1E112BCA007110C4 /* Products */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | DD9F199B1E112BCA007110C4 /* PiP Client.app */, 84 | ); 85 | name = Products; 86 | sourceTree = ""; 87 | }; 88 | DD9F199D1E112BCA007110C4 /* PiP Client */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | DD9F19B31E112BD7007110C4 /* Resources */, 92 | DD9F19B41E112BDB007110C4 /* Bootstrap */, 93 | DD9F19B51E112BDF007110C4 /* Controllers */, 94 | ); 95 | path = "PiP Client"; 96 | sourceTree = ""; 97 | }; 98 | DD9F19B31E112BD7007110C4 /* Resources */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | DD9F19A21E112BCA007110C4 /* Assets.xcassets */, 102 | DD9F19A41E112BCA007110C4 /* Main.storyboard */, 103 | DD9F19A71E112BCA007110C4 /* Info.plist */, 104 | ); 105 | name = Resources; 106 | sourceTree = ""; 107 | }; 108 | DD9F19B41E112BDB007110C4 /* Bootstrap */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | DD9F199E1E112BCA007110C4 /* AppDelegate.swift */, 112 | ); 113 | name = Bootstrap; 114 | sourceTree = ""; 115 | }; 116 | DD9F19B51E112BDF007110C4 /* Controllers */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | DD9F19A01E112BCA007110C4 /* PlayerViewController.swift */, 120 | ); 121 | name = Controllers; 122 | sourceTree = ""; 123 | }; 124 | DD9F19C91E112EAF007110C4 /* Products */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | DD9F19CD1E112EB0007110C4 /* PIPContainer.framework */, 128 | ); 129 | name = Products; 130 | sourceTree = ""; 131 | }; 132 | /* End PBXGroup section */ 133 | 134 | /* Begin PBXNativeTarget section */ 135 | DD9F199A1E112BCA007110C4 /* PiP Client */ = { 136 | isa = PBXNativeTarget; 137 | buildConfigurationList = DD9F19AA1E112BCA007110C4 /* Build configuration list for PBXNativeTarget "PiP Client" */; 138 | buildPhases = ( 139 | DD9F19971E112BCA007110C4 /* Sources */, 140 | DD9F19981E112BCA007110C4 /* Frameworks */, 141 | DD9F19991E112BCA007110C4 /* Resources */, 142 | DD9F19BA1E112C0B007110C4 /* Embed Frameworks */, 143 | ); 144 | buildRules = ( 145 | ); 146 | dependencies = ( 147 | DD9F19D11E112EB2007110C4 /* PBXTargetDependency */, 148 | ); 149 | name = "PiP Client"; 150 | productName = "PiP Client"; 151 | productReference = DD9F199B1E112BCA007110C4 /* PiP Client.app */; 152 | productType = "com.apple.product-type.application"; 153 | }; 154 | /* End PBXNativeTarget section */ 155 | 156 | /* Begin PBXProject section */ 157 | DD9F19931E112BCA007110C4 /* Project object */ = { 158 | isa = PBXProject; 159 | attributes = { 160 | LastSwiftUpdateCheck = 0810; 161 | LastUpgradeCheck = 0810; 162 | ORGANIZATIONNAME = "Guilherme Rambo"; 163 | TargetAttributes = { 164 | DD9F199A1E112BCA007110C4 = { 165 | CreatedOnToolsVersion = 8.1; 166 | DevelopmentTeam = 8C7439RJLG; 167 | ProvisioningStyle = Automatic; 168 | }; 169 | }; 170 | }; 171 | buildConfigurationList = DD9F19961E112BCA007110C4 /* Build configuration list for PBXProject "PiP Client" */; 172 | compatibilityVersion = "Xcode 3.2"; 173 | developmentRegion = English; 174 | hasScannedForEncodings = 0; 175 | knownRegions = ( 176 | en, 177 | Base, 178 | ); 179 | mainGroup = DD9F19921E112BCA007110C4; 180 | productRefGroup = DD9F199C1E112BCA007110C4 /* Products */; 181 | projectDirPath = ""; 182 | projectReferences = ( 183 | { 184 | ProductGroup = DD9F19C91E112EAF007110C4 /* Products */; 185 | ProjectRef = DD9F19C81E112EAF007110C4 /* PIPContainer.xcodeproj */; 186 | }, 187 | ); 188 | projectRoot = ""; 189 | targets = ( 190 | DD9F199A1E112BCA007110C4 /* PiP Client */, 191 | ); 192 | }; 193 | /* End PBXProject section */ 194 | 195 | /* Begin PBXReferenceProxy section */ 196 | DD9F19CD1E112EB0007110C4 /* PIPContainer.framework */ = { 197 | isa = PBXReferenceProxy; 198 | fileType = wrapper.framework; 199 | path = PIPContainer.framework; 200 | remoteRef = DD9F19CC1E112EB0007110C4 /* PBXContainerItemProxy */; 201 | sourceTree = BUILT_PRODUCTS_DIR; 202 | }; 203 | /* End PBXReferenceProxy section */ 204 | 205 | /* Begin PBXResourcesBuildPhase section */ 206 | DD9F19991E112BCA007110C4 /* Resources */ = { 207 | isa = PBXResourcesBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | DD9F19A31E112BCA007110C4 /* Assets.xcassets in Resources */, 211 | DD9F19A61E112BCA007110C4 /* Main.storyboard in Resources */, 212 | ); 213 | runOnlyForDeploymentPostprocessing = 0; 214 | }; 215 | /* End PBXResourcesBuildPhase section */ 216 | 217 | /* Begin PBXSourcesBuildPhase section */ 218 | DD9F19971E112BCA007110C4 /* Sources */ = { 219 | isa = PBXSourcesBuildPhase; 220 | buildActionMask = 2147483647; 221 | files = ( 222 | DD9F19A11E112BCA007110C4 /* PlayerViewController.swift in Sources */, 223 | DD9F199F1E112BCA007110C4 /* AppDelegate.swift in Sources */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXSourcesBuildPhase section */ 228 | 229 | /* Begin PBXTargetDependency section */ 230 | DD9F19D11E112EB2007110C4 /* PBXTargetDependency */ = { 231 | isa = PBXTargetDependency; 232 | name = PIPContainer; 233 | targetProxy = DD9F19D01E112EB2007110C4 /* PBXContainerItemProxy */; 234 | }; 235 | /* End PBXTargetDependency section */ 236 | 237 | /* Begin PBXVariantGroup section */ 238 | DD9F19A41E112BCA007110C4 /* Main.storyboard */ = { 239 | isa = PBXVariantGroup; 240 | children = ( 241 | DD9F19A51E112BCA007110C4 /* Base */, 242 | ); 243 | name = Main.storyboard; 244 | sourceTree = ""; 245 | }; 246 | /* End PBXVariantGroup section */ 247 | 248 | /* Begin XCBuildConfiguration section */ 249 | DD9F19A81E112BCA007110C4 /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | ALWAYS_SEARCH_USER_PATHS = NO; 253 | CLANG_ANALYZER_NONNULL = YES; 254 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 255 | CLANG_CXX_LIBRARY = "libc++"; 256 | CLANG_ENABLE_MODULES = YES; 257 | CLANG_ENABLE_OBJC_ARC = YES; 258 | CLANG_WARN_BOOL_CONVERSION = YES; 259 | CLANG_WARN_CONSTANT_CONVERSION = YES; 260 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 261 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 262 | CLANG_WARN_EMPTY_BODY = YES; 263 | CLANG_WARN_ENUM_CONVERSION = YES; 264 | CLANG_WARN_INFINITE_RECURSION = YES; 265 | CLANG_WARN_INT_CONVERSION = YES; 266 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 267 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 268 | CLANG_WARN_UNREACHABLE_CODE = YES; 269 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 270 | CODE_SIGN_IDENTITY = "-"; 271 | COPY_PHASE_STRIP = NO; 272 | DEBUG_INFORMATION_FORMAT = dwarf; 273 | ENABLE_STRICT_OBJC_MSGSEND = YES; 274 | ENABLE_TESTABILITY = YES; 275 | GCC_C_LANGUAGE_STANDARD = gnu99; 276 | GCC_DYNAMIC_NO_PIC = NO; 277 | GCC_NO_COMMON_BLOCKS = YES; 278 | GCC_OPTIMIZATION_LEVEL = 0; 279 | GCC_PREPROCESSOR_DEFINITIONS = ( 280 | "DEBUG=1", 281 | "$(inherited)", 282 | ); 283 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 284 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 285 | GCC_WARN_UNDECLARED_SELECTOR = YES; 286 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 287 | GCC_WARN_UNUSED_FUNCTION = YES; 288 | GCC_WARN_UNUSED_VARIABLE = YES; 289 | MACOSX_DEPLOYMENT_TARGET = 10.12; 290 | MTL_ENABLE_DEBUG_INFO = YES; 291 | ONLY_ACTIVE_ARCH = YES; 292 | SDKROOT = macosx; 293 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 294 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 295 | }; 296 | name = Debug; 297 | }; 298 | DD9F19A91E112BCA007110C4 /* Release */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | ALWAYS_SEARCH_USER_PATHS = NO; 302 | CLANG_ANALYZER_NONNULL = YES; 303 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 304 | CLANG_CXX_LIBRARY = "libc++"; 305 | CLANG_ENABLE_MODULES = YES; 306 | CLANG_ENABLE_OBJC_ARC = YES; 307 | CLANG_WARN_BOOL_CONVERSION = YES; 308 | CLANG_WARN_CONSTANT_CONVERSION = YES; 309 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 310 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 311 | CLANG_WARN_EMPTY_BODY = YES; 312 | CLANG_WARN_ENUM_CONVERSION = YES; 313 | CLANG_WARN_INFINITE_RECURSION = YES; 314 | CLANG_WARN_INT_CONVERSION = YES; 315 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 316 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 317 | CLANG_WARN_UNREACHABLE_CODE = YES; 318 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 319 | CODE_SIGN_IDENTITY = "-"; 320 | COPY_PHASE_STRIP = NO; 321 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 322 | ENABLE_NS_ASSERTIONS = NO; 323 | ENABLE_STRICT_OBJC_MSGSEND = YES; 324 | GCC_C_LANGUAGE_STANDARD = gnu99; 325 | GCC_NO_COMMON_BLOCKS = YES; 326 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 327 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 328 | GCC_WARN_UNDECLARED_SELECTOR = YES; 329 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 330 | GCC_WARN_UNUSED_FUNCTION = YES; 331 | GCC_WARN_UNUSED_VARIABLE = YES; 332 | MACOSX_DEPLOYMENT_TARGET = 10.12; 333 | MTL_ENABLE_DEBUG_INFO = NO; 334 | SDKROOT = macosx; 335 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 336 | }; 337 | name = Release; 338 | }; 339 | DD9F19AB1E112BCA007110C4 /* Debug */ = { 340 | isa = XCBuildConfiguration; 341 | buildSettings = { 342 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 343 | COMBINE_HIDPI_IMAGES = YES; 344 | DEVELOPMENT_TEAM = 8C7439RJLG; 345 | INFOPLIST_FILE = "PiP Client/Info.plist"; 346 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 347 | PRODUCT_BUNDLE_IDENTIFIER = "br.com.guilhermerambo.PiP-Client"; 348 | PRODUCT_NAME = "$(TARGET_NAME)"; 349 | SWIFT_VERSION = 3.0; 350 | }; 351 | name = Debug; 352 | }; 353 | DD9F19AC1E112BCA007110C4 /* Release */ = { 354 | isa = XCBuildConfiguration; 355 | buildSettings = { 356 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 357 | COMBINE_HIDPI_IMAGES = YES; 358 | DEVELOPMENT_TEAM = 8C7439RJLG; 359 | INFOPLIST_FILE = "PiP Client/Info.plist"; 360 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 361 | PRODUCT_BUNDLE_IDENTIFIER = "br.com.guilhermerambo.PiP-Client"; 362 | PRODUCT_NAME = "$(TARGET_NAME)"; 363 | SWIFT_VERSION = 3.0; 364 | }; 365 | name = Release; 366 | }; 367 | /* End XCBuildConfiguration section */ 368 | 369 | /* Begin XCConfigurationList section */ 370 | DD9F19961E112BCA007110C4 /* Build configuration list for PBXProject "PiP Client" */ = { 371 | isa = XCConfigurationList; 372 | buildConfigurations = ( 373 | DD9F19A81E112BCA007110C4 /* Debug */, 374 | DD9F19A91E112BCA007110C4 /* Release */, 375 | ); 376 | defaultConfigurationIsVisible = 0; 377 | defaultConfigurationName = Release; 378 | }; 379 | DD9F19AA1E112BCA007110C4 /* Build configuration list for PBXNativeTarget "PiP Client" */ = { 380 | isa = XCConfigurationList; 381 | buildConfigurations = ( 382 | DD9F19AB1E112BCA007110C4 /* Debug */, 383 | DD9F19AC1E112BCA007110C4 /* Release */, 384 | ); 385 | defaultConfigurationIsVisible = 0; 386 | defaultConfigurationName = Release; 387 | }; 388 | /* End XCConfigurationList section */ 389 | }; 390 | rootObject = DD9F19931E112BCA007110C4 /* Project object */; 391 | } 392 | -------------------------------------------------------------------------------- /Demo/Swift/PiP Client/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PiP Client 4 | // 5 | // Created by Guilherme Rambo on 26/12/16. 6 | // Copyright © 2016 Guilherme Rambo. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | @NSApplicationMain 12 | class AppDelegate: NSObject, NSApplicationDelegate { 13 | 14 | 15 | 16 | func applicationDidFinishLaunching(_ aNotification: Notification) { 17 | // Insert code here to initialize your application 18 | } 19 | 20 | func applicationWillTerminate(_ aNotification: Notification) { 21 | // Insert code here to tear down your application 22 | } 23 | 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /Demo/Swift/PiP Client/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /Demo/Swift/PiP Client/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | Default 511 | 512 | 513 | 514 | 515 | 516 | 517 | Left to Right 518 | 519 | 520 | 521 | 522 | 523 | 524 | Right to Left 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | Default 536 | 537 | 538 | 539 | 540 | 541 | 542 | Left to Right 543 | 544 | 545 | 546 | 547 | 548 | 549 | Right to Left 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | -------------------------------------------------------------------------------- /Demo/Swift/PiP Client/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2016 Guilherme Rambo. All rights reserved. 27 | NSMainStoryboardFile 28 | Main 29 | NSPrincipalClass 30 | NSApplication 31 | NSAppTransportSecurity 32 | 33 | NSAllowsArbitraryLoads 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Demo/Swift/PiP Client/PlayerViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PlayerViewController.swift 3 | // PiP Client 4 | // 5 | // Created by Guilherme Rambo on 26/12/16. 6 | // Copyright © 2016 Guilherme Rambo. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | import PIPContainer 12 | import AVFoundation 13 | 14 | class PlayerViewController: NSViewController { 15 | 16 | private struct Constants { 17 | static let video = "http://p.events-delivery.apple.com.edgesuite.net/16oibfvohbfvoihbdfvoihbefv10/m3u8/atv_vod_mvp.m3u8" 18 | } 19 | 20 | private var player: AVPlayer! 21 | 22 | private var pip: PIPContainerViewController? { 23 | return parent as? PIPContainerViewController 24 | } 25 | 26 | override func viewDidLoad() { 27 | super.viewDidLoad() 28 | 29 | guard let url = URL(string: Constants.video) else { return } 30 | 31 | player = AVPlayer(url: url) 32 | 33 | view.layer = AVPlayerLayer(player: player) 34 | view.layer?.backgroundColor = NSColor.black.cgColor 35 | 36 | player.seek(to: CMTimeMakeWithSeconds(912, Int32(NSEC_PER_SEC))) 37 | player.play() 38 | } 39 | 40 | override func viewDidAppear() { 41 | super.viewDidAppear() 42 | 43 | view.window?.titleVisibility = .hidden 44 | 45 | setupPIPSupport() 46 | } 47 | 48 | private func setupPIPSupport() { 49 | pip?.pipWillOpen = { [weak self] in 50 | guard let rate = self?.player.rate else { return } 51 | 52 | self?.pip?.isPlaying = (rate != 0.0) 53 | } 54 | 55 | pip?.pipDidPause = { [weak self] in 56 | self?.player.pause() 57 | } 58 | 59 | pip?.pipDidPlay = { [weak self] in 60 | self?.player.play() 61 | } 62 | } 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /Framework/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2016 Guilherme Rambo. All rights reserved. 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Framework/PIPContainer.h: -------------------------------------------------------------------------------- 1 | // 2 | // PIPContainer.h 3 | // PIPContainer 4 | // 5 | // Created by Guilherme Rambo on 26/12/16. 6 | // Copyright © 2016 Guilherme Rambo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for PIPContainer. 12 | FOUNDATION_EXPORT double PIPContainerVersionNumber; 13 | 14 | //! Project version string for PIPContainer. 15 | FOUNDATION_EXPORT const unsigned char PIPContainerVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | #import 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Guilherme Rambo 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | - Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | - Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /PIPContainer.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'PIPContainer' 3 | s.version = '1.0.0' 4 | s.summary = 'An easy to use interface for picture-in-picture on macOS 10.12 and later.' 5 | s.homepage = 'https://github.com/insidegui/PIPContainer' 6 | s.description = 'A view controller subclass to contain other view controllers to be presented in picture-in-picture mode' 7 | 8 | s.license = { :type => 'BSD' } 9 | s.authors = 'Guilherme Rambo' 10 | s.social_media_url = 'https://twitter.com/_inside' 11 | s.source = { 12 | :git => 'https://github.com/insidegui/PIPContainer.git', 13 | :tag => s.version.to_s, 14 | :branch => 'master' 15 | } 16 | 17 | s.osx.source_files = 'Sources/**/*.{h,m}' 18 | s.osx.private_header_files = 'Sources/Private/*.h' 19 | s.osx.deployment_target = '10.12' 20 | 21 | s.requires_arc = true 22 | 23 | s.xcconfig = {'FRAMEWORK_SEARCH_PATHS' => '/System/Library/PrivateFrameworks'} 24 | s.osx.frameworks = ['Cocoa', 'PIP'] 25 | end 26 | -------------------------------------------------------------------------------- /PIPContainer.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | DD9F197D1E112A9E007110C4 /* PIPContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9F197B1E112A9E007110C4 /* PIPContainer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | DD9F197F1E112AAF007110C4 /* PIP.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9F197E1E112AAF007110C4 /* PIP.h */; }; 12 | DD9F19821E112AB6007110C4 /* PIPContainerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9F19801E112AB6007110C4 /* PIPContainerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | DD9F19831E112AB6007110C4 /* PIPContainerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9F19811E112AB6007110C4 /* PIPContainerViewController.m */; }; 14 | DD9F19861E112AC9007110C4 /* PIP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD9F19851E112AC9007110C4 /* PIP.framework */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | DD9F196C1E112A3E007110C4 /* PIPContainer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PIPContainer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 19 | DD9F197A1E112A9E007110C4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Framework/Info.plist; sourceTree = SOURCE_ROOT; }; 20 | DD9F197B1E112A9E007110C4 /* PIPContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PIPContainer.h; path = Framework/PIPContainer.h; sourceTree = SOURCE_ROOT; }; 21 | DD9F197E1E112AAF007110C4 /* PIP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PIP.h; path = Sources/Private/PIP.h; sourceTree = SOURCE_ROOT; }; 22 | DD9F19801E112AB6007110C4 /* PIPContainerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PIPContainerViewController.h; path = Sources/PIPContainerViewController.h; sourceTree = SOURCE_ROOT; }; 23 | DD9F19811E112AB6007110C4 /* PIPContainerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PIPContainerViewController.m; path = Sources/PIPContainerViewController.m; sourceTree = SOURCE_ROOT; }; 24 | DD9F19851E112AC9007110C4 /* PIP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PIP.framework; path = ../../../../../System/Library/PrivateFrameworks/PIP.framework; sourceTree = ""; }; 25 | /* End PBXFileReference section */ 26 | 27 | /* Begin PBXFrameworksBuildPhase section */ 28 | DD9F19681E112A3E007110C4 /* Frameworks */ = { 29 | isa = PBXFrameworksBuildPhase; 30 | buildActionMask = 2147483647; 31 | files = ( 32 | DD9F19861E112AC9007110C4 /* PIP.framework in Frameworks */, 33 | ); 34 | runOnlyForDeploymentPostprocessing = 0; 35 | }; 36 | /* End PBXFrameworksBuildPhase section */ 37 | 38 | /* Begin PBXGroup section */ 39 | DD9F19621E112A3E007110C4 = { 40 | isa = PBXGroup; 41 | children = ( 42 | DD9F196E1E112A3E007110C4 /* PIPContainer */, 43 | DD9F196D1E112A3E007110C4 /* Products */, 44 | DD9F19841E112AC9007110C4 /* Frameworks */, 45 | ); 46 | sourceTree = ""; 47 | }; 48 | DD9F196D1E112A3E007110C4 /* Products */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | DD9F196C1E112A3E007110C4 /* PIPContainer.framework */, 52 | ); 53 | name = Products; 54 | sourceTree = ""; 55 | }; 56 | DD9F196E1E112A3E007110C4 /* PIPContainer */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | DD9F19781E112A7D007110C4 /* Sources */, 60 | DD9F19771E112A79007110C4 /* Framework */, 61 | ); 62 | path = PIPContainer; 63 | sourceTree = ""; 64 | }; 65 | DD9F19771E112A79007110C4 /* Framework */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | DD9F197A1E112A9E007110C4 /* Info.plist */, 69 | DD9F197B1E112A9E007110C4 /* PIPContainer.h */, 70 | ); 71 | path = Framework; 72 | sourceTree = ""; 73 | }; 74 | DD9F19781E112A7D007110C4 /* Sources */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | DD9F19801E112AB6007110C4 /* PIPContainerViewController.h */, 78 | DD9F19811E112AB6007110C4 /* PIPContainerViewController.m */, 79 | DD9F19791E112A8C007110C4 /* Private */, 80 | ); 81 | path = Sources; 82 | sourceTree = ""; 83 | }; 84 | DD9F19791E112A8C007110C4 /* Private */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | DD9F197E1E112AAF007110C4 /* PIP.h */, 88 | ); 89 | path = Private; 90 | sourceTree = ""; 91 | }; 92 | DD9F19841E112AC9007110C4 /* Frameworks */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | DD9F19851E112AC9007110C4 /* PIP.framework */, 96 | ); 97 | name = Frameworks; 98 | sourceTree = ""; 99 | }; 100 | /* End PBXGroup section */ 101 | 102 | /* Begin PBXHeadersBuildPhase section */ 103 | DD9F19691E112A3E007110C4 /* Headers */ = { 104 | isa = PBXHeadersBuildPhase; 105 | buildActionMask = 2147483647; 106 | files = ( 107 | DD9F197F1E112AAF007110C4 /* PIP.h in Headers */, 108 | DD9F19821E112AB6007110C4 /* PIPContainerViewController.h in Headers */, 109 | DD9F197D1E112A9E007110C4 /* PIPContainer.h in Headers */, 110 | ); 111 | runOnlyForDeploymentPostprocessing = 0; 112 | }; 113 | /* End PBXHeadersBuildPhase section */ 114 | 115 | /* Begin PBXNativeTarget section */ 116 | DD9F196B1E112A3E007110C4 /* PIPContainer */ = { 117 | isa = PBXNativeTarget; 118 | buildConfigurationList = DD9F19741E112A3E007110C4 /* Build configuration list for PBXNativeTarget "PIPContainer" */; 119 | buildPhases = ( 120 | DD9F19671E112A3E007110C4 /* Sources */, 121 | DD9F19681E112A3E007110C4 /* Frameworks */, 122 | DD9F19691E112A3E007110C4 /* Headers */, 123 | DD9F196A1E112A3E007110C4 /* Resources */, 124 | ); 125 | buildRules = ( 126 | ); 127 | dependencies = ( 128 | ); 129 | name = PIPContainer; 130 | productName = PIPContainer; 131 | productReference = DD9F196C1E112A3E007110C4 /* PIPContainer.framework */; 132 | productType = "com.apple.product-type.framework"; 133 | }; 134 | /* End PBXNativeTarget section */ 135 | 136 | /* Begin PBXProject section */ 137 | DD9F19631E112A3E007110C4 /* Project object */ = { 138 | isa = PBXProject; 139 | attributes = { 140 | LastUpgradeCheck = 0820; 141 | ORGANIZATIONNAME = "Guilherme Rambo"; 142 | TargetAttributes = { 143 | DD9F196B1E112A3E007110C4 = { 144 | CreatedOnToolsVersion = 8.1; 145 | DevelopmentTeam = 8C7439RJLG; 146 | ProvisioningStyle = Automatic; 147 | }; 148 | }; 149 | }; 150 | buildConfigurationList = DD9F19661E112A3E007110C4 /* Build configuration list for PBXProject "PIPContainer" */; 151 | compatibilityVersion = "Xcode 3.2"; 152 | developmentRegion = English; 153 | hasScannedForEncodings = 0; 154 | knownRegions = ( 155 | en, 156 | ); 157 | mainGroup = DD9F19621E112A3E007110C4; 158 | productRefGroup = DD9F196D1E112A3E007110C4 /* Products */; 159 | projectDirPath = ""; 160 | projectRoot = ""; 161 | targets = ( 162 | DD9F196B1E112A3E007110C4 /* PIPContainer */, 163 | ); 164 | }; 165 | /* End PBXProject section */ 166 | 167 | /* Begin PBXResourcesBuildPhase section */ 168 | DD9F196A1E112A3E007110C4 /* Resources */ = { 169 | isa = PBXResourcesBuildPhase; 170 | buildActionMask = 2147483647; 171 | files = ( 172 | ); 173 | runOnlyForDeploymentPostprocessing = 0; 174 | }; 175 | /* End PBXResourcesBuildPhase section */ 176 | 177 | /* Begin PBXSourcesBuildPhase section */ 178 | DD9F19671E112A3E007110C4 /* Sources */ = { 179 | isa = PBXSourcesBuildPhase; 180 | buildActionMask = 2147483647; 181 | files = ( 182 | DD9F19831E112AB6007110C4 /* PIPContainerViewController.m in Sources */, 183 | ); 184 | runOnlyForDeploymentPostprocessing = 0; 185 | }; 186 | /* End PBXSourcesBuildPhase section */ 187 | 188 | /* Begin XCBuildConfiguration section */ 189 | DD9F19721E112A3E007110C4 /* Debug */ = { 190 | isa = XCBuildConfiguration; 191 | buildSettings = { 192 | ALWAYS_SEARCH_USER_PATHS = NO; 193 | CLANG_ANALYZER_NONNULL = YES; 194 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 195 | CLANG_CXX_LIBRARY = "libc++"; 196 | CLANG_ENABLE_MODULES = YES; 197 | CLANG_ENABLE_OBJC_ARC = YES; 198 | CLANG_WARN_BOOL_CONVERSION = YES; 199 | CLANG_WARN_CONSTANT_CONVERSION = YES; 200 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 201 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 202 | CLANG_WARN_EMPTY_BODY = YES; 203 | CLANG_WARN_ENUM_CONVERSION = YES; 204 | CLANG_WARN_INFINITE_RECURSION = YES; 205 | CLANG_WARN_INT_CONVERSION = YES; 206 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 207 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 208 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 209 | CLANG_WARN_UNREACHABLE_CODE = YES; 210 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 211 | CODE_SIGN_IDENTITY = "-"; 212 | COPY_PHASE_STRIP = NO; 213 | CURRENT_PROJECT_VERSION = 1; 214 | DEBUG_INFORMATION_FORMAT = dwarf; 215 | ENABLE_STRICT_OBJC_MSGSEND = YES; 216 | ENABLE_TESTABILITY = YES; 217 | GCC_C_LANGUAGE_STANDARD = gnu99; 218 | GCC_DYNAMIC_NO_PIC = NO; 219 | GCC_NO_COMMON_BLOCKS = YES; 220 | GCC_OPTIMIZATION_LEVEL = 0; 221 | GCC_PREPROCESSOR_DEFINITIONS = ( 222 | "DEBUG=1", 223 | "$(inherited)", 224 | ); 225 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 226 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 227 | GCC_WARN_UNDECLARED_SELECTOR = YES; 228 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 229 | GCC_WARN_UNUSED_FUNCTION = YES; 230 | GCC_WARN_UNUSED_VARIABLE = YES; 231 | MACOSX_DEPLOYMENT_TARGET = 10.12; 232 | MTL_ENABLE_DEBUG_INFO = YES; 233 | ONLY_ACTIVE_ARCH = YES; 234 | SDKROOT = macosx; 235 | VERSIONING_SYSTEM = "apple-generic"; 236 | VERSION_INFO_PREFIX = ""; 237 | }; 238 | name = Debug; 239 | }; 240 | DD9F19731E112A3E007110C4 /* Release */ = { 241 | isa = XCBuildConfiguration; 242 | buildSettings = { 243 | ALWAYS_SEARCH_USER_PATHS = NO; 244 | CLANG_ANALYZER_NONNULL = YES; 245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 246 | CLANG_CXX_LIBRARY = "libc++"; 247 | CLANG_ENABLE_MODULES = YES; 248 | CLANG_ENABLE_OBJC_ARC = YES; 249 | CLANG_WARN_BOOL_CONVERSION = YES; 250 | CLANG_WARN_CONSTANT_CONVERSION = YES; 251 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 252 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 253 | CLANG_WARN_EMPTY_BODY = YES; 254 | CLANG_WARN_ENUM_CONVERSION = YES; 255 | CLANG_WARN_INFINITE_RECURSION = YES; 256 | CLANG_WARN_INT_CONVERSION = YES; 257 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 258 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | CODE_SIGN_IDENTITY = "-"; 263 | COPY_PHASE_STRIP = NO; 264 | CURRENT_PROJECT_VERSION = 1; 265 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 266 | ENABLE_NS_ASSERTIONS = NO; 267 | ENABLE_STRICT_OBJC_MSGSEND = YES; 268 | GCC_C_LANGUAGE_STANDARD = gnu99; 269 | GCC_NO_COMMON_BLOCKS = YES; 270 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 271 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 272 | GCC_WARN_UNDECLARED_SELECTOR = YES; 273 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 274 | GCC_WARN_UNUSED_FUNCTION = YES; 275 | GCC_WARN_UNUSED_VARIABLE = YES; 276 | MACOSX_DEPLOYMENT_TARGET = 10.12; 277 | MTL_ENABLE_DEBUG_INFO = NO; 278 | SDKROOT = macosx; 279 | VERSIONING_SYSTEM = "apple-generic"; 280 | VERSION_INFO_PREFIX = ""; 281 | }; 282 | name = Release; 283 | }; 284 | DD9F19751E112A3E007110C4 /* Debug */ = { 285 | isa = XCBuildConfiguration; 286 | buildSettings = { 287 | CODE_SIGN_IDENTITY = ""; 288 | COMBINE_HIDPI_IMAGES = YES; 289 | DEFINES_MODULE = YES; 290 | DEVELOPMENT_TEAM = 8C7439RJLG; 291 | DYLIB_COMPATIBILITY_VERSION = 1; 292 | DYLIB_CURRENT_VERSION = 1; 293 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 294 | FRAMEWORK_SEARCH_PATHS = ( 295 | "$(inherited)", 296 | "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", 297 | ); 298 | FRAMEWORK_VERSION = A; 299 | INFOPLIST_FILE = Framework/Info.plist; 300 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 301 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 302 | PRODUCT_BUNDLE_IDENTIFIER = br.com.guilhermerambo.PIPContainer; 303 | PRODUCT_NAME = "$(TARGET_NAME)"; 304 | SKIP_INSTALL = YES; 305 | }; 306 | name = Debug; 307 | }; 308 | DD9F19761E112A3E007110C4 /* Release */ = { 309 | isa = XCBuildConfiguration; 310 | buildSettings = { 311 | CODE_SIGN_IDENTITY = ""; 312 | COMBINE_HIDPI_IMAGES = YES; 313 | DEFINES_MODULE = YES; 314 | DEVELOPMENT_TEAM = 8C7439RJLG; 315 | DYLIB_COMPATIBILITY_VERSION = 1; 316 | DYLIB_CURRENT_VERSION = 1; 317 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 318 | FRAMEWORK_SEARCH_PATHS = ( 319 | "$(inherited)", 320 | "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", 321 | ); 322 | FRAMEWORK_VERSION = A; 323 | INFOPLIST_FILE = Framework/Info.plist; 324 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 325 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 326 | PRODUCT_BUNDLE_IDENTIFIER = br.com.guilhermerambo.PIPContainer; 327 | PRODUCT_NAME = "$(TARGET_NAME)"; 328 | SKIP_INSTALL = YES; 329 | }; 330 | name = Release; 331 | }; 332 | /* End XCBuildConfiguration section */ 333 | 334 | /* Begin XCConfigurationList section */ 335 | DD9F19661E112A3E007110C4 /* Build configuration list for PBXProject "PIPContainer" */ = { 336 | isa = XCConfigurationList; 337 | buildConfigurations = ( 338 | DD9F19721E112A3E007110C4 /* Debug */, 339 | DD9F19731E112A3E007110C4 /* Release */, 340 | ); 341 | defaultConfigurationIsVisible = 0; 342 | defaultConfigurationName = Release; 343 | }; 344 | DD9F19741E112A3E007110C4 /* Build configuration list for PBXNativeTarget "PIPContainer" */ = { 345 | isa = XCConfigurationList; 346 | buildConfigurations = ( 347 | DD9F19751E112A3E007110C4 /* Debug */, 348 | DD9F19761E112A3E007110C4 /* Release */, 349 | ); 350 | defaultConfigurationIsVisible = 0; 351 | defaultConfigurationName = Release; 352 | }; 353 | /* End XCConfigurationList section */ 354 | }; 355 | rootObject = DD9F19631E112A3E007110C4 /* Project object */; 356 | } 357 | -------------------------------------------------------------------------------- /PIPContainer.xcodeproj/xcshareddata/xcschemes/PIPContainer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PIPContainer 2 | 3 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![CocoaPods](https://img.shields.io/cocoapods/v/PIPContainer.svg)]() 4 | 5 | An `NSViewController` subclass that can present its child view controller in picture-in-picture mode. 6 | 7 | Please note that this project links against `PIP.framework`, which is private. Don't try to submit apps using this to the App Store. 8 | 9 | ![demo](./Screenshots/pipdemo.gif) 10 | 11 | # Integration 12 | 13 | ## Carthage 14 | 15 | Add the following line to your `Cartfile` and follow the [integration instructions for Carthage](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application): 16 | 17 | ``` 18 | github "insidegui/PIPContainer" ~> 1.0 19 | ``` 20 | 21 | ## CocoaPods 22 | 23 | Add the following line to your `Podfile` and then run `pod install`: 24 | 25 | ``` 26 | pod 'PIPContainer' 27 | ``` 28 | 29 | ## Manually 30 | 31 | Drag `PIPContainer.xcodeproj` to your project and add `PIPContainer.framework` to the `Embedded Binaries` section. 32 | 33 | ![manual integration](./Screenshots/embedded-binaries.png) 34 | 35 | # Usage 36 | 37 | ## Containment 38 | 39 | The way it works is you add the view controller you want to display in the PiP as a child view controller of `PIPContainerViewController`. This can all be done using storyboards ([see demos](./Demo)). 40 | 41 | ![storyboard containment](./Screenshots/containment.png) 42 | 43 | ## Entering and Exiting PiP mode 44 | 45 | After you have the correct containment setup, simply call `togglePIP` on `PIPContainerViewController` to enter/exit PiP mode. 46 | 47 | ```swift 48 | private var pip: PIPContainerViewController? { 49 | return parent as? PIPContainerViewController 50 | } 51 | 52 | func togglePictureInPictureMode() { 53 | pip?.togglePIP(nil) 54 | } 55 | ``` 56 | 57 | You can also link UI controls like buttons and menus directly to the `togglePIP` action in Interface Builder by control-dragging to the First Responder and selecting the action `togglePIP:`. 58 | 59 | ## Getting notified about PiP commands 60 | 61 | `PIPContainerViewController` has many block properties that you can use to get notifications about state changes. 62 | 63 | - `pipDidPause`: Called when the pause button is pressed in the PiP panel 64 | - `pipDidPlay`: Called when the play button is pressed in the PiP panel 65 | - `pipWillOpen`: Called when the PiP panel is about to be opened. This is the best moment to set the `isPlaying` property of `PIPContainerViewController` to reflect the state of your player 66 | - `pipWillClose`: Called when the PiP panel is about to be closed 67 | - `pipDidClose`: Called after the PiP panel is closed and the view controller is back to its original position 68 | 69 | ## Demos 70 | 71 | I encourage you to have a look at the demos to get a better understanding of how PIPContainer works: 72 | 73 | - [ObjC demo](./Demo/ObjC) 74 | - [Swift demo](./Demo/Swift) 75 | -------------------------------------------------------------------------------- /Screenshots/containment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/insidegui/PIPContainer/c5779813b17a2bad967bf4a6b6b7711166ae0dbc/Screenshots/containment.png -------------------------------------------------------------------------------- /Screenshots/embedded-binaries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/insidegui/PIPContainer/c5779813b17a2bad967bf4a6b6b7711166ae0dbc/Screenshots/embedded-binaries.png -------------------------------------------------------------------------------- /Screenshots/pipdemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/insidegui/PIPContainer/c5779813b17a2bad967bf4a6b6b7711166ae0dbc/Screenshots/pipdemo.gif -------------------------------------------------------------------------------- /Sources/PIPContainerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PIPContainerViewController.h 3 | // 4 | // Created by Guilherme Rambo on 30/10/16. 5 | // Copyright © 2016 Guilherme Rambo. All rights reserved. 6 | // 7 | 8 | @import Cocoa; 9 | 10 | /// A view controller to contain other view controllers to be presented in picture-in-picture mode 11 | @interface PIPContainerViewController : NSViewController 12 | 13 | /// Toggles picture-in-picture state for the first child view controller 14 | - (IBAction)togglePIP:(nullable id)sender; 15 | 16 | /// Called when the pause button is pressed in the PiP panel 17 | @property (nonatomic, copy, nullable) void (^pipDidPause)(); 18 | 19 | /// Called when the play button is pressed in the PiP panel 20 | @property (nonatomic, copy, nullable) void (^pipDidPlay)(); 21 | 22 | /// Called when the PiP panel is about to be opened (TIP: set the isPlaying property here) 23 | @property (nonatomic, copy, nullable) void (^pipWillOpen)(); 24 | 25 | /// Called when the PiP panel is about to be closed 26 | @property (nonatomic, copy, nullable) void (^pipWillClose)(); 27 | 28 | /// Called after the PiP panel is closed and the view controller is back to its original position 29 | @property (nonatomic, copy, nullable) void (^pipDidClose)(); 30 | 31 | /// Set this property so the PiP panel reflects the current state when presented 32 | @property (nonatomic, assign, getter=isPlaying) BOOL playing; 33 | 34 | /// Whether the PIP is currently presenting its child view controller in picture-in-picture 35 | @property (nonatomic, readonly, getter=isActive) BOOL active; 36 | 37 | @end 38 | 39 | -------------------------------------------------------------------------------- /Sources/PIPContainerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PIPContainerViewController.m 3 | // 4 | // Created by Guilherme Rambo on 30/10/16. 5 | // Copyright © 2016 Guilherme Rambo. All rights reserved. 6 | // 7 | 8 | #import "PIPContainerViewController.h" 9 | 10 | #import "PIP.h" 11 | 12 | @interface PIPContainerViewController () 13 | 14 | @property (nonatomic, strong) PIPViewController *pip; 15 | @property (assign) BOOL isInPip; 16 | @property (weak) NSViewController *viewControllerForPip; 17 | 18 | @end 19 | 20 | @implementation PIPContainerViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | self.view.wantsLayer = YES; 26 | self.view.layer.backgroundColor = [NSColor blackColor].CGColor; 27 | } 28 | 29 | - (IBAction)togglePIP:(id)sender 30 | { 31 | if (self.isInPip) { 32 | [self __prepareForPipExit]; 33 | [self.pip dismissViewController:self.viewControllerForPip]; 34 | } else { 35 | dispatch_async(dispatch_get_main_queue(), ^{ 36 | if (self.pipWillOpen) self.pipWillOpen(); 37 | }); 38 | 39 | self.viewControllerForPip = self.childViewControllers.firstObject; 40 | [self.pip presentViewControllerAsPictureInPicture:self.viewControllerForPip]; 41 | self.isInPip = YES; 42 | } 43 | } 44 | 45 | - (void)__prepareForPipExit 46 | { 47 | // exiting PiP mode when the app is not active doesn't look right, so we make sure the app is active before the PiP exits here 48 | if (!NSApp.isActive) { 49 | [NSApp activateIgnoringOtherApps:YES]; 50 | [self.view.window makeKeyAndOrderFront:nil]; 51 | } 52 | 53 | // deminiaturize the window when exiting PiP mode 54 | if (self.view.window.isMiniaturized) { 55 | [self.view.window deminiaturize:nil]; 56 | } 57 | 58 | // setup the pip for exiting 59 | self.pip.replacementRect = self.view.frame; 60 | self.pip.replacementWindow = self.view.window; 61 | self.pip.replacementView = self.view; 62 | } 63 | 64 | - (void)__finishPipExit 65 | { 66 | // when the PiP is closed, it doesn't add the view back to the original superview, we have to do it manually 67 | self.viewControllerForPip.view.frame = self.view.bounds; 68 | [self.view addSubview:self.viewControllerForPip.view]; 69 | self.viewControllerForPip.view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; 70 | } 71 | 72 | - (PIPViewController *)pip 73 | { 74 | if (!_pip) { 75 | _pip = [[PIPViewController alloc] init]; 76 | [_pip setAspectRatio:self.view.frame.size]; 77 | [_pip setDelegate:self]; 78 | } 79 | 80 | return _pip; 81 | } 82 | 83 | - (void)setPlaying:(BOOL)playing 84 | { 85 | _playing = playing; 86 | 87 | [self.pip setPlaying:playing]; 88 | } 89 | 90 | #pragma mark PIPViewControllerDelegate 91 | 92 | - (void)pipWillClose:(PIPViewController *)pip 93 | { 94 | if (self.pipWillClose) { 95 | dispatch_async(dispatch_get_main_queue(), ^{ 96 | if (self.pipWillClose) self.pipWillClose(); 97 | }); 98 | } 99 | 100 | [self __prepareForPipExit]; 101 | } 102 | 103 | - (void)pipDidClose:(PIPViewController *)pip 104 | { 105 | [self __finishPipExit]; 106 | 107 | // pip is not needed (until the user clicks "toggle pip" again) 108 | self.pip = nil; 109 | self.isInPip = NO; 110 | 111 | if (self.pipDidClose) { 112 | dispatch_async(dispatch_get_main_queue(), ^{ 113 | if (self.pipDidClose) self.pipDidClose(); 114 | }); 115 | } 116 | } 117 | 118 | - (void)pipActionPlay:(PIPViewController *)pip 119 | { 120 | if (self.pipDidPlay) { 121 | dispatch_async(dispatch_get_main_queue(), ^{ 122 | if (self.pipDidPlay) self.pipDidPlay(); 123 | }); 124 | } 125 | } 126 | 127 | - (void)pipActionPause:(PIPViewController *)pip 128 | { 129 | if (self.pipDidPause) { 130 | dispatch_async(dispatch_get_main_queue(), ^{ 131 | if (self.pipDidPause) self.pipDidPause(); 132 | }); 133 | } 134 | } 135 | 136 | - (BOOL)isActive 137 | { 138 | return _isInPip; 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /Sources/Private/PIP.h: -------------------------------------------------------------------------------- 1 | // 2 | // PIP.h 3 | // PiP Client 4 | // 5 | // Created by Guilherme Rambo on 30/10/16. 6 | // Copyright © 2016 Guilherme Rambo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class PIPViewController; 12 | 13 | @protocol PIPViewControllerDelegate 14 | 15 | @optional 16 | - (void)pipActionStop:(PIPViewController *)pip; 17 | - (void)pipActionPause:(PIPViewController *)pip; 18 | - (void)pipActionPlay:(PIPViewController *)pip; 19 | - (void)pipActionReturn:(PIPViewController *)pip; 20 | - (void)pipDidClose:(PIPViewController *)pip; 21 | - (void)pipWillClose:(PIPViewController *)pip; 22 | @end 23 | 24 | @interface PIPViewController : NSViewController 25 | 26 | @property (nonatomic, weak) id delegate; 27 | @property (nonatomic, assign) NSRect replacementRect; 28 | @property (nonatomic, weak) NSWindow *replacementWindow; 29 | @property (nonatomic, weak) NSView *replacementView; 30 | @property (nonatomic, copy) NSString *name; 31 | @property (nonatomic, assign) NSSize aspectRatio; 32 | 33 | - (void)presentViewControllerAsPictureInPicture:(__kindof NSViewController *)controller; 34 | - (void)performWindowDragWithEvent:(id)arg1; 35 | - (void)setPlaying:(BOOL)playing; 36 | - (BOOL)playing; 37 | 38 | - (instancetype)init; 39 | 40 | @end 41 | --------------------------------------------------------------------------------