OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #import "ARDVideoCallView.h" | |
12 | |
13 #import <AVFoundation/AVFoundation.h> | |
14 #import "UIImage+ARDUtilities.h" | |
15 | |
16 static CGFloat const kButtonPadding = 16; | |
17 static CGFloat const kButtonSize = 48; | |
18 static CGFloat const kLocalVideoViewSize = 120; | |
19 static CGFloat const kLocalVideoViewPadding = 8; | |
20 static CGFloat const kStatusBarHeight = 20; | |
21 | |
22 @interface ARDVideoCallView () <RTCEAGLVideoViewDelegate> | |
23 @end | |
24 | |
25 @implementation ARDVideoCallView { | |
26 UIButton *_routeChangeButton; | |
27 UIButton *_cameraSwitchButton; | |
28 UIButton *_hangupButton; | |
29 CGSize _remoteVideoSize; | |
30 BOOL _useRearCamera; | |
31 } | |
32 | |
33 @synthesize statusLabel = _statusLabel; | |
34 @synthesize localVideoView = _localVideoView; | |
35 @synthesize remoteVideoView = _remoteVideoView; | |
36 @synthesize statsView = _statsView; | |
37 @synthesize delegate = _delegate; | |
38 | |
39 - (instancetype)initWithFrame:(CGRect)frame { | |
40 if (self = [super initWithFrame:frame]) { | |
41 _remoteVideoView = [[RTCEAGLVideoView alloc] initWithFrame:CGRectZero]; | |
42 _remoteVideoView.delegate = self; | |
43 [self addSubview:_remoteVideoView]; | |
44 | |
45 _localVideoView = [[RTCCameraPreviewView alloc] initWithFrame:CGRectZero]; | |
46 [self addSubview:_localVideoView]; | |
47 | |
48 _statsView = [[ARDStatsView alloc] initWithFrame:CGRectZero]; | |
49 _statsView.hidden = YES; | |
50 [self addSubview:_statsView]; | |
51 | |
52 _routeChangeButton = [UIButton buttonWithType:UIButtonTypeCustom]; | |
53 _routeChangeButton.backgroundColor = [UIColor whiteColor]; | |
54 _routeChangeButton.layer.cornerRadius = kButtonSize / 2; | |
55 _routeChangeButton.layer.masksToBounds = YES; | |
56 UIImage *image = [UIImage imageNamed:@"ic_surround_sound_black_24dp.png"]; | |
57 [_routeChangeButton setImage:image forState:UIControlStateNormal]; | |
58 [_routeChangeButton addTarget:self | |
59 action:@selector(onRouteChange:) | |
60 forControlEvents:UIControlEventTouchUpInside]; | |
61 [self addSubview:_routeChangeButton]; | |
62 | |
63 // TODO(tkchin): don't display this if we can't actually do camera switch. | |
64 _cameraSwitchButton = [UIButton buttonWithType:UIButtonTypeCustom]; | |
65 _cameraSwitchButton.backgroundColor = [UIColor whiteColor]; | |
66 _cameraSwitchButton.layer.cornerRadius = kButtonSize / 2; | |
67 _cameraSwitchButton.layer.masksToBounds = YES; | |
68 image = [UIImage imageNamed:@"ic_switch_video_black_24dp.png"]; | |
69 [_cameraSwitchButton setImage:image forState:UIControlStateNormal]; | |
70 [_cameraSwitchButton addTarget:self | |
71 action:@selector(onCameraSwitch:) | |
72 forControlEvents:UIControlEventTouchUpInside]; | |
73 [self addSubview:_cameraSwitchButton]; | |
74 | |
75 _hangupButton = [UIButton buttonWithType:UIButtonTypeCustom]; | |
76 _hangupButton.backgroundColor = [UIColor redColor]; | |
77 _hangupButton.layer.cornerRadius = kButtonSize / 2; | |
78 _hangupButton.layer.masksToBounds = YES; | |
79 image = [UIImage imageForName:@"ic_call_end_black_24dp.png" | |
80 color:[UIColor whiteColor]]; | |
81 [_hangupButton setImage:image forState:UIControlStateNormal]; | |
82 [_hangupButton addTarget:self | |
83 action:@selector(onHangup:) | |
84 forControlEvents:UIControlEventTouchUpInside]; | |
85 [self addSubview:_hangupButton]; | |
86 | |
87 _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero]; | |
88 _statusLabel.font = [UIFont fontWithName:@"Roboto" size:16]; | |
89 _statusLabel.textColor = [UIColor whiteColor]; | |
90 [self addSubview:_statusLabel]; | |
91 | |
92 UITapGestureRecognizer *tapRecognizer = | |
93 [[UITapGestureRecognizer alloc] | |
94 initWithTarget:self | |
95 action:@selector(didTripleTap:)]; | |
96 tapRecognizer.numberOfTapsRequired = 3; | |
97 [self addGestureRecognizer:tapRecognizer]; | |
98 } | |
99 return self; | |
100 } | |
101 | |
102 - (void)layoutSubviews { | |
103 CGRect bounds = self.bounds; | |
104 if (_remoteVideoSize.width > 0 && _remoteVideoSize.height > 0) { | |
105 // Aspect fill remote video into bounds. | |
106 CGRect remoteVideoFrame = | |
107 AVMakeRectWithAspectRatioInsideRect(_remoteVideoSize, bounds); | |
108 CGFloat scale = 1; | |
109 if (remoteVideoFrame.size.width > remoteVideoFrame.size.height) { | |
110 // Scale by height. | |
111 scale = bounds.size.height / remoteVideoFrame.size.height; | |
112 } else { | |
113 // Scale by width. | |
114 scale = bounds.size.width / remoteVideoFrame.size.width; | |
115 } | |
116 remoteVideoFrame.size.height *= scale; | |
117 remoteVideoFrame.size.width *= scale; | |
118 _remoteVideoView.frame = remoteVideoFrame; | |
119 _remoteVideoView.center = | |
120 CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds)); | |
121 } else { | |
122 _remoteVideoView.frame = bounds; | |
123 } | |
124 | |
125 // Aspect fit local video view into a square box. | |
126 CGRect localVideoFrame = | |
127 CGRectMake(0, 0, kLocalVideoViewSize, kLocalVideoViewSize); | |
128 // Place the view in the bottom right. | |
129 localVideoFrame.origin.x = CGRectGetMaxX(bounds) | |
130 - localVideoFrame.size.width - kLocalVideoViewPadding; | |
131 localVideoFrame.origin.y = CGRectGetMaxY(bounds) | |
132 - localVideoFrame.size.height - kLocalVideoViewPadding; | |
133 _localVideoView.frame = localVideoFrame; | |
134 | |
135 // Place stats at the top. | |
136 CGSize statsSize = [_statsView sizeThatFits:bounds.size]; | |
137 _statsView.frame = CGRectMake(CGRectGetMinX(bounds), | |
138 CGRectGetMinY(bounds) + kStatusBarHeight, | |
139 statsSize.width, statsSize.height); | |
140 | |
141 // Place hangup button in the bottom left. | |
142 _hangupButton.frame = | |
143 CGRectMake(CGRectGetMinX(bounds) + kButtonPadding, | |
144 CGRectGetMaxY(bounds) - kButtonPadding - | |
145 kButtonSize, | |
146 kButtonSize, | |
147 kButtonSize); | |
148 | |
149 // Place button to the right of hangup button. | |
150 CGRect cameraSwitchFrame = _hangupButton.frame; | |
151 cameraSwitchFrame.origin.x = | |
152 CGRectGetMaxX(cameraSwitchFrame) + kButtonPadding; | |
153 _cameraSwitchButton.frame = cameraSwitchFrame; | |
154 | |
155 // Place route button to the right of camera button. | |
156 CGRect routeChangeFrame = _cameraSwitchButton.frame; | |
157 routeChangeFrame.origin.x = | |
158 CGRectGetMaxX(routeChangeFrame) + kButtonPadding; | |
159 _routeChangeButton.frame = routeChangeFrame; | |
160 | |
161 [_statusLabel sizeToFit]; | |
162 _statusLabel.center = | |
163 CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds)); | |
164 } | |
165 | |
166 #pragma mark - RTCEAGLVideoViewDelegate | |
167 | |
168 - (void)videoView:(RTCEAGLVideoView*)videoView didChangeVideoSize:(CGSize)size { | |
169 if (videoView == _remoteVideoView) { | |
170 _remoteVideoSize = size; | |
171 } | |
172 [self setNeedsLayout]; | |
173 } | |
174 | |
175 #pragma mark - Private | |
176 | |
177 - (void)onCameraSwitch:(id)sender { | |
178 [_delegate videoCallViewDidSwitchCamera:self]; | |
179 } | |
180 | |
181 - (void)onRouteChange:(id)sender { | |
182 [_delegate videoCallViewDidChangeRoute:self]; | |
183 } | |
184 | |
185 - (void)onHangup:(id)sender { | |
186 [_delegate videoCallViewDidHangup:self]; | |
187 } | |
188 | |
189 - (void)didTripleTap:(UITapGestureRecognizer *)recognizer { | |
190 [_delegate videoCallViewDidEnableStats:self]; | |
191 } | |
192 | |
193 @end | |
OLD | NEW |