Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit b5c1076

Browse files
committed
wip, adding play button functionality
1 parent 0cc229d commit b5c1076

27 files changed

Lines changed: 1227 additions & 0 deletions

AsyncDisplayKit.xcodeproj/project.pbxproj

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@
351351
ACF6ED611B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED591B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm */; };
352352
ACF6ED621B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED5A1B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm */; };
353353
ACF6ED631B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED5B1B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm */; };
354+
AEEC47E11C20C2DD00EC1693 /* ASVideoNode.h in Headers */ = {isa = PBXBuildFile; fileRef = AEEC47DF1C20C2DD00EC1693 /* ASVideoNode.h */; };
355+
AEEC47E21C20C2DD00EC1693 /* ASVideoNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = AEEC47E01C20C2DD00EC1693 /* ASVideoNode.mm */; };
356+
AEEC47E41C21D3D200EC1693 /* ASVideoNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.m */; };
354357
B0F8805A1BEAEC7500D17647 /* ASTableNode.h in Headers */ = {isa = PBXBuildFile; fileRef = B0F880581BEAEC7500D17647 /* ASTableNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
355358
B0F8805B1BEAEC7500D17647 /* ASTableNode.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F880591BEAEC7500D17647 /* ASTableNode.m */; };
356359
B35061F31B010EFD0018CF92 /* ASCellNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 055F1A3A19ABD43F004DAFF1 /* ASCellNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -736,6 +739,9 @@
736739
ACF6ED591B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASOverlayLayoutSpecSnapshotTests.mm; sourceTree = "<group>"; };
737740
ACF6ED5A1B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRatioLayoutSpecSnapshotTests.mm; sourceTree = "<group>"; };
738741
ACF6ED5B1B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASStackLayoutSpecSnapshotTests.mm; sourceTree = "<group>"; };
742+
AEEC47DF1C20C2DD00EC1693 /* ASVideoNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASVideoNode.h; sourceTree = "<group>"; };
743+
AEEC47E01C20C2DD00EC1693 /* ASVideoNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASVideoNode.mm; sourceTree = "<group>"; };
744+
AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASVideoNodeTests.m; sourceTree = "<group>"; };
739745
B0F880581BEAEC7500D17647 /* ASTableNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTableNode.h; sourceTree = "<group>"; };
740746
B0F880591BEAEC7500D17647 /* ASTableNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTableNode.m; sourceTree = "<group>"; };
741747
B35061DA1B010EDF0018CF92 /* AsyncDisplayKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AsyncDisplayKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -867,6 +873,8 @@
867873
children = (
868874
92DD2FE11BF4B97E0074C9DD /* ASMapNode.h */,
869875
92DD2FE21BF4B97E0074C9DD /* ASMapNode.mm */,
876+
AEEC47DF1C20C2DD00EC1693 /* ASVideoNode.h */,
877+
AEEC47E01C20C2DD00EC1693 /* ASVideoNode.mm */,
870878
055F1A3A19ABD43F004DAFF1 /* ASCellNode.h */,
871879
AC6456071B0A335000CF11B8 /* ASCellNode.m */,
872880
18C2ED7C1B9B7DE800F627B3 /* ASCollectionNode.h */,
@@ -960,6 +968,7 @@
960968
254C6B531BF8FF2A003EC431 /* ASTextKitTests.mm */,
961969
058D0A36195D057000B7D73C /* ASTextNodeTests.m */,
962970
058D0A37195D057000B7D73C /* ASTextNodeWordKernerTests.mm */,
971+
AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.m */,
963972
058D09C6195D04C000B7D73C /* Supporting Files */,
964973
052EE06A1A15A0D8002C6279 /* TestResources */,
965974
2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m */,
@@ -1254,6 +1263,7 @@
12541263
18C2ED7E1B9B7DE800F627B3 /* ASCollectionNode.h in Headers */,
12551264
257754C01BEE458E00737CA5 /* ASTextNodeWordKerner.h in Headers */,
12561265
AC3C4A511A1139C100143C57 /* ASCollectionView.h in Headers */,
1266+
AEEC47E11C20C2DD00EC1693 /* ASVideoNode.h in Headers */,
12571267
205F0E1D1B373A2C007741D0 /* ASCollectionViewLayoutController.h in Headers */,
12581268
AC3C4A541A113EEC00143C57 /* ASCollectionViewProtocols.h in Headers */,
12591269
058D0A49195D05CB00B7D73C /* ASControlNode+Subclasses.h in Headers */,
@@ -1513,6 +1523,7 @@
15131523
058D09B9195D04C000B7D73C /* Frameworks */,
15141524
058D09BA195D04C000B7D73C /* Resources */,
15151525
3B9D88CDF51B429C8409E4B6 /* Copy Pods Resources */,
1526+
527A806066E1F4E2795090DF /* Embed Pods Frameworks */,
15161527
);
15171528
buildRules = (
15181529
);
@@ -1642,6 +1653,21 @@
16421653
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-resources.sh\"\n";
16431654
showEnvVarsInLog = 0;
16441655
};
1656+
527A806066E1F4E2795090DF /* Embed Pods Frameworks */ = {
1657+
isa = PBXShellScriptBuildPhase;
1658+
buildActionMask = 2147483647;
1659+
files = (
1660+
);
1661+
inputPaths = (
1662+
);
1663+
name = "Embed Pods Frameworks";
1664+
outputPaths = (
1665+
);
1666+
runOnlyForDeploymentPostprocessing = 0;
1667+
shellPath = /bin/sh;
1668+
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-frameworks.sh\"\n";
1669+
showEnvVarsInLog = 0;
1670+
};
16451671
/* End PBXShellScriptBuildPhase section */
16461672

16471673
/* Begin PBXSourcesBuildPhase section */
@@ -1689,6 +1715,7 @@
16891715
058D0A2A195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm in Sources */,
16901716
058D0A14195D050800B7D73C /* ASDisplayNode.mm in Sources */,
16911717
058D0A15195D050800B7D73C /* ASDisplayNodeExtras.mm in Sources */,
1718+
AEEC47E21C20C2DD00EC1693 /* ASVideoNode.mm in Sources */,
16921719
0587F9BE1A7309ED00AFF0BA /* ASEditableTextNode.mm in Sources */,
16931720
464052231A3F83C40061C0BA /* ASFlowLayoutController.mm in Sources */,
16941721
257754C41BEE458E00737CA5 /* ASTextNodeWordKerner.m in Sources */,
@@ -1775,6 +1802,7 @@
17751802
05EA6FE71AC0966E00E35788 /* ASSnapshotTestCase.mm in Sources */,
17761803
ACF6ED631B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm in Sources */,
17771804
3C9C128519E616EF00E942A0 /* ASTableViewTests.m in Sources */,
1805+
AEEC47E41C21D3D200EC1693 /* ASVideoNodeTests.m in Sources */,
17781806
254C6B521BF8FE6D003EC431 /* ASTextKitTruncationTests.mm in Sources */,
17791807
058D0A3D195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.m in Sources */,
17801808
058D0A40195D057000B7D73C /* ASTextNodeTests.m in Sources */,

AsyncDisplayKit/ASButtonNode.mm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
212212
return stack;
213213
}
214214

215+
- (void)layoutDidFinish
216+
{
217+
218+
}
219+
215220
- (void)layout
216221
{
217222
[super layout];

AsyncDisplayKit/ASVideoNode.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
#import <AsyncDisplayKit/AsyncDisplayKit.h>
3+
4+
typedef NS_ENUM(NSUInteger, ASVideoGravity) {
5+
ASVideoGravityResizeAspect,
6+
ASVideoGravityResizeAspectFill,
7+
ASVideoGravityResize
8+
};
9+
10+
// set up boolean to repeat video
11+
// set up delegate methods to provide play button
12+
// tapping should play and pause
13+
14+
@interface ASVideoNode : ASDisplayNode
15+
@property (atomic, strong, readwrite) AVAsset *asset;
16+
@property (nonatomic, assign, readwrite) BOOL shouldRepeat;
17+
@property (atomic) ASVideoGravity gravity;
18+
@property (atomic) BOOL autorepeat;
19+
@property (atomic) ASButtonNode *playButton;
20+
21+
- (void)play;
22+
- (void)pause;
23+
24+
@end
25+
26+
@protocol ASVideoNodeDelegate <NSObject>
27+
@end
28+
29+
@protocol ASVideoNodeDatasource <NSObject>
30+
@optional
31+
- (ASDisplayNode *)playButtonForVideoNode:(ASVideoNode *) videoNode;
32+
- (UIImage *)thumbnailForVideoNode:(ASVideoNode *) videoNode;
33+
- (NSURL *)thumbnailURLForVideoNode:(ASVideoNode *)videoNode;
34+
@end

AsyncDisplayKit/ASVideoNode.mm

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
2+
3+
#import "ASVideoNode.h"
4+
5+
@interface ASVideoNode () {
6+
ASDN::RecursiveMutex _lock;
7+
8+
__weak id<ASVideoNodeDatasource> _datasource;
9+
10+
AVPlayer *_player;
11+
BOOL _shouldBePlaying;
12+
AVAsset *_asset;
13+
ASButtonNode *_playButton;
14+
ASDisplayNode *_playerNode;
15+
}
16+
17+
@end
18+
19+
@implementation ASVideoNode
20+
21+
- (instancetype)init {
22+
if (!(self = [super init])) { return nil; }
23+
24+
_playerNode = [[ASDisplayNode alloc] initWithLayerBlock:^CALayer *{ return [[AVPlayerLayer alloc] init]; }];
25+
[self addSubnode:_playerNode];
26+
27+
self.gravity = ASVideoGravityResizeAspect;
28+
29+
return self;
30+
}
31+
32+
- (void)layoutDidFinish
33+
{
34+
_playerNode.frame = self.bounds;
35+
}
36+
37+
- (instancetype)initWithViewBlock:(ASDisplayNodeViewBlock)viewBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock
38+
{
39+
ASDisplayNodeAssertNotSupported();
40+
return nil;
41+
}
42+
43+
- (void)fetchData
44+
{
45+
[super fetchData];
46+
47+
{
48+
ASDN::MutexLocker l(_lock);
49+
AVPlayerItem *item = [[AVPlayerItem alloc] initWithAsset:_asset];
50+
((AVPlayerLayer *)_playerNode.layer).player = [[AVPlayer alloc] initWithPlayerItem:item];
51+
if (_shouldBePlaying) {
52+
[[((AVPlayerLayer *)_playerNode.layer) player] play];
53+
}
54+
}
55+
}
56+
57+
- (void)clearFetchedData
58+
{
59+
[super clearFetchedData];
60+
61+
{
62+
ASDN::MutexLocker l(_lock);
63+
((AVPlayerLayer *)_playerNode.layer).player = nil;
64+
_shouldBePlaying = NO;
65+
}
66+
}
67+
68+
- (void)setPlayButton:(ASButtonNode *)playButton
69+
{
70+
ASDN::MutexLocker l(_lock);
71+
72+
_playButton = playButton;
73+
74+
[self addSubnode:playButton];
75+
[self.view bringSubviewToFront:playButton.view];
76+
77+
[_playButton addTarget:self action:@selector(playButtonWasTouchedUpInside) forControlEvents:ASControlNodeEventTouchUpInside];
78+
}
79+
80+
- (void)playButtonWasTouchedUpInside
81+
{
82+
[self play];
83+
}
84+
85+
- (ASButtonNode *)playButton
86+
{
87+
ASDN::MutexLocker l(_lock);
88+
89+
return _playButton;
90+
}
91+
92+
- (void)setAsset:(AVAsset *)asset
93+
{
94+
ASDN::MutexLocker l(_lock);
95+
96+
if (ASObjectIsEqual(((AVURLAsset *)asset).URL, ((AVURLAsset *)_asset).URL)) {
97+
return;
98+
}
99+
100+
_asset = asset;
101+
102+
if (self.interfaceState & ASInterfaceStateFetchData) {
103+
[self fetchData];
104+
}
105+
}
106+
107+
- (AVAsset *)asset
108+
{
109+
return _asset;
110+
}
111+
112+
- (void)setGravity:(ASVideoGravity)gravity {
113+
ASDN::MutexLocker l(_lock);
114+
115+
switch (gravity) {
116+
case ASVideoGravityResize:
117+
((AVPlayerLayer *)_playerNode.layer).videoGravity = AVLayerVideoGravityResize;
118+
break;
119+
case ASVideoGravityResizeAspect:
120+
((AVPlayerLayer *)_playerNode.layer).videoGravity = AVLayerVideoGravityResizeAspect;
121+
break;
122+
case ASVideoGravityResizeAspectFill:
123+
((AVPlayerLayer *)_playerNode.layer).videoGravity = AVLayerVideoGravityResizeAspectFill;
124+
break;
125+
default:
126+
((AVPlayerLayer *)_playerNode.layer).videoGravity = AVLayerVideoGravityResizeAspect;
127+
break;
128+
}
129+
}
130+
131+
- (ASVideoGravity)gravity;
132+
{
133+
ASDN::MutexLocker l(_lock);
134+
135+
if ([((AVPlayerLayer *)_playerNode.layer).contentsGravity isEqualToString:AVLayerVideoGravityResize]) {
136+
return ASVideoGravityResize;
137+
}
138+
if ([((AVPlayerLayer *)_playerNode.layer).contentsGravity isEqualToString:AVLayerVideoGravityResizeAspectFill]) {
139+
return ASVideoGravityResizeAspectFill;
140+
}
141+
142+
return ASVideoGravityResizeAspect;
143+
}
144+
145+
- (void)play;
146+
{
147+
ASDN::MutexLocker l(_lock);
148+
149+
[[((AVPlayerLayer *)_playerNode.layer) player] play];
150+
_shouldBePlaying = YES;
151+
}
152+
153+
- (void)pause;
154+
{
155+
ASDN::MutexLocker l(_lock);
156+
157+
[[((AVPlayerLayer *)_playerNode.layer) player] pause];
158+
_shouldBePlaying = NO;
159+
}
160+
161+
@end
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/* Copyright (c) 2014-present, Facebook, Inc.
2+
* All rights reserved.
3+
*
4+
* This source code is licensed under the BSD-style license found in the
5+
* LICENSE file in the root directory of this source tree. An additional grant
6+
* of patent rights can be found in the PATENTS file in the same directory.
7+
*/
8+
9+
#import <UIKit/UIKit.h>
10+
#import <XCTest/XCTest.h>
11+
#import "ASVideoNode.h"
12+
13+
@interface ASVideoNodeTests : XCTestCase
14+
15+
@end
16+
17+
@implementation ASVideoNodeTests
18+
19+
- (void)testVideoNodeReplacesAVPlayerWhenNewURLIsSet {
20+
ASVideoNode *videoNode = [[ASVideoNode alloc] init];
21+
videoNode.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"firstURL"]];
22+
[videoNode fetchData];
23+
AVPlayer *player = ((AVPlayerLayer *)videoNode.layer).player;
24+
25+
videoNode.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"secondURL"]];
26+
[videoNode fetchData];
27+
AVPlayer *secondPlayer = ((AVPlayerLayer *)videoNode.layer).player;
28+
29+
XCTAssertNotEqualObjects(player, secondPlayer);
30+
}
31+
32+
- (void)testVideoNodeDoesNotMakeNewPlayerWhenURLIsTheSame {
33+
ASVideoNode *videoNode = [[ASVideoNode alloc] init];
34+
videoNode.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"firstURL"]];
35+
[videoNode fetchData];
36+
37+
AVPlayer *firstPlayer = ((AVPlayerLayer *)videoNode.layer).player;
38+
videoNode.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"firstURL"]];
39+
40+
AVPlayer *secondPlayer = ((AVPlayerLayer *)videoNode.layer).player;
41+
42+
XCTAssertEqualObjects(firstPlayer, secondPlayer);
43+
}
44+
45+
@end
17.1 KB
Loading
17.9 KB
Loading
22.8 KB
Loading

examples/Videos/Podfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
source 'https://github.com/CocoaPods/Specs.git'
2+
platform :ios, '8.0'
3+
pod 'AsyncDisplayKit', :path => '../..'

0 commit comments

Comments
 (0)