Skip to content
This repository was archived by the owner on Jan 13, 2022. It is now read-only.

Commit 6566c55

Browse files
author
Brandon Walkin
committed
Added the source code for Origami Live
1 parent 487ac4b commit 6566c55

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+3616
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2016-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*
8+
*/
9+
10+
#import <CoreGraphics/CoreGraphics.h>
11+
#import <Foundation/Foundation.h>
12+
13+
#import <peertalk/PTChannel.h>
14+
15+
@class AVAudioRecorder;
16+
@class BWViewController;
17+
@class CMMotionManager;
18+
19+
@protocol BWDeviceInfoTransmitterDelegate;
20+
21+
@interface BWDeviceInfoTransmitter : NSObject <PTChannelDelegate>
22+
23+
@property (weak, nonatomic) id<BWDeviceInfoTransmitterDelegate> delegate;
24+
@property (weak, nonatomic) BWViewController *mainViewController;
25+
26+
@property (retain, nonatomic) NSDictionary *touches;
27+
@property (retain, nonatomic) CMMotionManager *motionManager;
28+
@property (retain, nonatomic) NSMutableDictionary *deviceInformation;
29+
@property (retain, nonatomic) NSMutableDictionary *deviceData;
30+
@property (retain, nonatomic) AVAudioRecorder *recorder;
31+
@property CGFloat screenScale;
32+
33+
+ (BWDeviceInfoTransmitter *)sharedTransmitter;
34+
- (void)initialSetup;
35+
- (void)listen;
36+
37+
@end
38+
39+
40+
@protocol BWDeviceInfoTransmitterDelegate <NSObject>
41+
42+
- (void)deviceInfoTransmitterDidConnect:(BWDeviceInfoTransmitter *)transmitte;
43+
- (void)deviceInfoTransmitterDidDisconnect:(BWDeviceInfoTransmitter *)transmitte;
44+
45+
@end
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
/*
2+
* Copyright (c) 2016-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*
8+
*/
9+
10+
#import "BWDeviceInfoTransmitter.h"
11+
12+
#import <AVFoundation/AVFoundation.h>
13+
#import <CoreMotion/CoreMotion.h>
14+
#import <QuartzCore/QuartzCore.h>
15+
16+
#import "BWPeerTalkAdditions.h"
17+
#import "BWViewController.h"
18+
#import "FBDeviceProtocol.h"
19+
20+
static BWDeviceInfoTransmitter *sharedSingleton;
21+
22+
static CGFloat RadiansToDegrees(double radians) {
23+
return radians * 180 / M_PI;
24+
};
25+
26+
@interface BWDeviceInfoTransmitter () {
27+
__weak PTChannel *serverChannel_;
28+
__weak PTChannel *peerChannel_;
29+
}
30+
- (void)sendData:(id)data forFrameType:(FBFrameType)frameType;
31+
@end
32+
33+
@implementation BWDeviceInfoTransmitter
34+
35+
@synthesize touches = _touches;
36+
@synthesize motionManager = _motionManager;
37+
@synthesize screenScale = _screenScale;
38+
@synthesize deviceInformation = _deviceInformation;
39+
@synthesize deviceData = _deviceData;
40+
@synthesize recorder = _recorder;
41+
42+
+ (void)initialize
43+
{
44+
static BOOL initialized = NO;
45+
if (!initialized) {
46+
initialized = YES;
47+
sharedSingleton = [[BWDeviceInfoTransmitter alloc] init];
48+
}
49+
}
50+
51+
+ (BWDeviceInfoTransmitter *)sharedTransmitter {
52+
return sharedSingleton;
53+
}
54+
55+
- (void)initialSetup {
56+
[self listen];
57+
self.screenScale = [[UIScreen mainScreen] scale];
58+
59+
self.motionManager = [[CMMotionManager alloc] init];
60+
[self.motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical];
61+
62+
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateScreen:)];
63+
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
64+
65+
UIScreen *screen = [UIScreen mainScreen];
66+
UIDevice *device = [UIDevice currentDevice];
67+
self.deviceInformation = [NSMutableDictionary dictionaryWithObjectsAndKeys:
68+
@(device.userInterfaceIdiom), @"isTablet",
69+
@((screen.scale > 1.01)), @"retina",
70+
device.name, @"name",
71+
device.systemName, @"systemName",
72+
device.systemVersion, @"systemVersion",
73+
device.model, @"model",
74+
device.localizedModel, @"localizedModel",
75+
nil];
76+
77+
BOOL isPortrait = UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]);
78+
self.deviceData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
79+
@(isPortrait), @"isPortrait",
80+
@(screen.bounds.size.width * screen.scale),@"screenWidth",
81+
@(screen.bounds.size.height * screen.scale),@"screenHeight",
82+
nil];
83+
}
84+
85+
- (void)listen {
86+
PTChannel *channel = [PTChannel channelWithDelegate:self];
87+
[channel listenOnPort:FBProtocolIPv4PortNumber IPv4Address:INADDR_LOOPBACK callback:^(NSError *error) {
88+
if (error) {
89+
// NSLog(@"Failed to listen on 127.0.0.1:%d: %@", FBProtocolIPv4PortNumber, error);
90+
} else {
91+
// NSLog(@"Listening on 127.0.0.1:%d", FBProtocolIPv4PortNumber);
92+
serverChannel_ = channel;
93+
}
94+
}];
95+
}
96+
97+
- (void)updateScreen:(CADisplayLink *)displayLink {
98+
[self collectSensorData];
99+
[self sendData:self.deviceData forFrameType:FBFrameTypeSensorData];
100+
}
101+
102+
- (void)collectSensorData {
103+
NSArray *touches = self.touches.allValues;
104+
BWViewController *mainViewController = self.mainViewController;
105+
CGSize viewSize = mainViewController.view.bounds.size;
106+
107+
// Touches -- Should probably be moved out of here
108+
NSMutableDictionary *deviceInfoTouches = [NSMutableDictionary dictionary];
109+
110+
for (UITouch *touch in touches) {
111+
CGPoint position = [touch locationInView:mainViewController.view];
112+
113+
// Convert to the QC co-ordinate system. Origin in the center, max point top right.
114+
position.x = position.x - viewSize.width / 2;
115+
position.y = viewSize.height - (position.y + (viewSize.height / 2));
116+
117+
NSNumber *positionX = @(position.x * self.screenScale);
118+
NSNumber *positionY = @(position.y * self.screenScale);
119+
NSNumber *phase = @(touch.phase);
120+
NSNumber *size = [touch respondsToSelector:@selector(majorRadius)] ? @(touch.majorRadius) : @0.0;
121+
NSNumber *sizeTolerance = [touch respondsToSelector:@selector(majorRadiusTolerance)] ? @(touch.majorRadiusTolerance) : @0.0;
122+
123+
NSDictionary *touchDictionary = @{@"x": positionX, @"y": positionY, @"phase": phase, @"size": size, @"sizeTolerance": sizeTolerance};
124+
125+
#if FB_IOS9_SDK_OR_LATER
126+
127+
if ([touch respondsToSelector:@selector(force)]) {
128+
NSNumber *force = @(touch.force);
129+
[touchDictionary setValue:force forKey:@"force"];
130+
}
131+
132+
if ([touch respondsToSelector:@selector(maximumPossibleForce)]) {
133+
NSNumber *maxForce = @(touch.maximumPossibleForce);
134+
[touchDictionary setValue:maxForce forKey:@"maximumPossibleForce"];
135+
}
136+
137+
#endif
138+
139+
NSString *pointerAddress = [NSString stringWithFormat:@"%p", touch];
140+
deviceInfoTouches[pointerAddress] = touchDictionary;
141+
}
142+
143+
(self.deviceData)[@"touches"] = deviceInfoTouches;
144+
145+
// Gyroscope
146+
CMAttitude *attitude = self.motionManager.deviceMotion.attitude;
147+
NSNumber *pitch = [NSNumber numberWithDouble:RadiansToDegrees(attitude.pitch)];
148+
NSNumber *roll = [NSNumber numberWithDouble:RadiansToDegrees(attitude.roll)];
149+
NSNumber *yaw = [NSNumber numberWithDouble:RadiansToDegrees(attitude.yaw)];
150+
NSNumber *quaternionX = [NSNumber numberWithDouble:attitude.quaternion.x];
151+
NSNumber *quaternionY = [NSNumber numberWithDouble:attitude.quaternion.y];
152+
NSNumber *quaternionZ = [NSNumber numberWithDouble:attitude.quaternion.z];
153+
NSNumber *quaternionW = [NSNumber numberWithDouble:attitude.quaternion.w];
154+
NSDictionary *deviceInfoGyroscope = @{@"pitch": pitch, @"roll": roll, @"yaw": yaw, @"quaternionX": quaternionX, @"quaternionY": quaternionY, @"quaternionZ": quaternionZ, @"quaternionW": quaternionW};
155+
(self.deviceData)[@"gyroscope"] = deviceInfoGyroscope;
156+
157+
// Acceleromter
158+
CMAcceleration acceleration = self.motionManager.deviceMotion.userAcceleration;
159+
NSNumber *x = @(acceleration.x);
160+
NSNumber *y = @(acceleration.y);
161+
NSNumber *z = @(acceleration.z);
162+
NSDictionary *deviceInfoAcceleration = @{@"x": x, @"y": y, @"z": z};
163+
(self.deviceData)[@"acceleration"] = deviceInfoAcceleration;
164+
165+
// Rotation Rate
166+
CMRotationRate rotationRate = self.motionManager.deviceMotion.rotationRate;
167+
NSNumber *rateX = @(rotationRate.x);
168+
NSNumber *rateY = @(rotationRate.y);
169+
NSNumber *rateZ = @(rotationRate.z);
170+
NSDictionary *deviceInfoRotationRate = @{@"x": rateX, @"y": rateY, @"z": rateZ};
171+
(self.deviceData)[@"rotationRate"] = deviceInfoRotationRate;
172+
}
173+
174+
- (void)sendData:(id)data forFrameType:(FBFrameType)frameType {
175+
if ([data respondsToSelector:@selector(createReferencingDispatchData)]) {
176+
dispatch_data_t payload = [data createReferencingDispatchData];
177+
[peerChannel_ sendFrameOfType:frameType tag:PTFrameNoTag withPayload:payload callback:^(NSError *error) {
178+
if (error) {
179+
// NSLog(@"Failed to send data for frame type %u: %@",frameType,error);
180+
}
181+
}];
182+
}
183+
}
184+
185+
#pragma mark - PTChannelDelegate
186+
187+
// Invoked to accept an incoming frame on a channel. Reply NO ignore the
188+
// incoming frame. If not implemented by the delegate, all frames are accepted.
189+
- (BOOL)ioFrameChannel:(PTChannel*)channel shouldAcceptFrameOfType:(uint32_t)type tag:(uint32_t)tag payloadSize:(uint32_t)payloadSize {
190+
if (channel != peerChannel_) {
191+
// A previous channel that has been canceled but not yet ended. Ignore.
192+
return NO;
193+
} else if (type != FBFrameTypeLayerTree &&
194+
type != FBFrameTypeLayerChanges &&
195+
type != FBFrameTypeLayerRemoval &&
196+
type != FBFrameTypeImage &&
197+
type != FBFrameTypeVibration) {
198+
// NSLog(@"Unexpected frame of type %u", type);
199+
[channel close];
200+
return NO;
201+
} else {
202+
return YES;
203+
}
204+
}
205+
206+
// Invoked when a new frame has arrived on a channel.
207+
- (void)ioFrameChannel:(PTChannel*)channel didReceiveFrameOfType:(uint32_t)type tag:(uint32_t)tag payload:(PTData*)payload {
208+
BWViewController *mainViewController = self.mainViewController;
209+
210+
if (type == FBFrameTypeLayerTree) {
211+
NSArray *layerTree = [NSArray arrayWithContentsOfDispatchData:payload.dispatchData];
212+
213+
[mainViewController removeAllViews];
214+
// NSLog(@"[Tree] Removing all layers. Setting up tree: %@",layerTree);
215+
[mainViewController createViewHierarchyFromTree:layerTree];
216+
}
217+
218+
else if (type == FBFrameTypeLayerChanges) {
219+
NSDictionary *layers = [NSDictionary dictionaryWithContentsOfDispatchData:payload.dispatchData];
220+
[mainViewController applyChanges:layers];
221+
// NSLog(@"[Change]");
222+
}
223+
224+
else if (type == FBFrameTypeLayerRemoval) {
225+
NSArray *patchIDs = [NSArray arrayWithContentsOfDispatchData:payload.dispatchData];
226+
// NSLog(@"[Removal]: %@",patchIDs);
227+
for (NSString *patchID in patchIDs) {
228+
[mainViewController removeViewWithID:patchID];
229+
}
230+
}
231+
232+
else if (type == FBFrameTypeImage) {
233+
assert(payload != nil);
234+
NSData *imageData = [NSData dataWithContentsOfDispatchData:payload.dispatchData];
235+
236+
if (imageData) {
237+
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfDispatchData:payload.dispatchData];
238+
239+
// Data only has one image at the moment.
240+
for (NSString *imageKey in dict.allKeys) {
241+
NSArray *parts = [imageKey componentsSeparatedByString:@","];
242+
NSString *imageHash = parts[0];
243+
NSString *layerKey = parts[1];
244+
245+
NSData *innerImageData = dict[imageKey];
246+
UIImage *image = [UIImage imageWithData:innerImageData];
247+
[mainViewController setImage:image withHash:imageHash layerKey:layerKey];
248+
// NSLog(@"[Image]: Set image with hash: %@ Layer Key: %@",imageHash,layerKey);
249+
}
250+
251+
// Tell the Mac that we successfully received the image(s), and we're ready for another one for those layers
252+
[self sendData:dict.allKeys forFrameType:FBFrameTypeImageReceived];
253+
}
254+
}
255+
256+
else if (type == FBFrameTypeVibration) {
257+
NSDictionary *vibDict = [NSDictionary dictionaryWithContentsOfDispatchData:payload.dispatchData];
258+
BOOL state = [(NSNumber *)vibDict[@"state"] boolValue];
259+
260+
if (state) {
261+
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
262+
}
263+
}
264+
}
265+
266+
// Invoked when the channel closed. If it closed because of an error, *error* is
267+
// a non-nil NSError object.
268+
- (void)ioFrameChannel:(PTChannel*)channel didEndWithError:(NSError*)error {
269+
if (error) {
270+
// NSLog(@"%@ ended with error: %@", channel, error);
271+
} else {
272+
// NSLog(@"Disconnected from %@", channel.userInfo);
273+
BWViewController *mainViewController = self.mainViewController;
274+
if (mainViewController.view.subviews.count < 1) {
275+
[self.delegate deviceInfoTransmitterDidDisconnect:self];
276+
// [appDelegate setConnected:NO];
277+
}
278+
279+
[self listen];
280+
}
281+
}
282+
283+
// For listening channels, this method is invoked when a new connection has been
284+
// accepted.
285+
- (void)ioFrameChannel:(PTChannel*)channel didAcceptConnection:(PTChannel*)otherChannel fromAddress:(PTAddress*)address {
286+
// Cancel any other connection. We are FIFO, so the last connection
287+
// established will cancel any previous connection and "take its place".
288+
if (peerChannel_) {
289+
[peerChannel_ cancel];
290+
}
291+
292+
// Weak pointer to current connection. Connection objects live by themselves
293+
// (owned by its parent dispatch queue) until they are closed.
294+
peerChannel_ = otherChannel;
295+
peerChannel_.userInfo = address;
296+
// NSLog(@"Connected to %@", address);
297+
298+
// BWAppDelegate *appDelegate = (BWAppDelegate *)[[UIApplication sharedApplication] delegate];
299+
// [appDelegate setConnected:YES];
300+
[self.delegate deviceInfoTransmitterDidConnect:self];
301+
302+
// Send some information about ourselves to the other end
303+
[self sendData:self.deviceInformation forFrameType:FBFrameTypeDeviceInfo];
304+
}
305+
306+
307+
@end
308+
//
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (c) 2016-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*
8+
*/
9+
10+
#import <UIKit/UIKit.h>
11+
12+
@interface BWImageCache : NSCache
13+
14+
+ (instancetype)imageCache;
15+
16+
- (UIImage *)imageForKey:(NSString *)key;
17+
- (void)setImage:(UIImage *)image forKey:(NSString *)key;
18+
19+
@end

0 commit comments

Comments
 (0)