blob: b2647630e1f2e692ef4f7e334dd8778a23a7df53 [file] [log] [blame]
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +00001/*
Donald E Curtisa8736442015-08-05 15:48:13 -07002 * Copyright 2015 The WebRTC Project Authors. All rights reserved.
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +00003 *
Donald E Curtisa8736442015-08-05 15:48:13 -07004 * 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.
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +00009 */
10
11#import "ARDMainView.h"
12
13#import "UIImage+ARDUtilities.h"
14
15// TODO(tkchin): retrieve status bar height dynamically.
16static CGFloat const kStatusBarHeight = 20;
17
18static CGFloat const kRoomTextButtonSize = 40;
19static CGFloat const kRoomTextFieldHeight = 40;
20static CGFloat const kRoomTextFieldMargin = 8;
haysc913e6452015-10-02 11:44:03 -070021static CGFloat const kCallControlMargin = 8;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000022static CGFloat const kAppLabelHeight = 20;
23
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000024// Helper view that contains a text field and a clear button.
25@interface ARDRoomTextField : UIView <UITextFieldDelegate>
haysc913e6452015-10-02 11:44:03 -070026@property(nonatomic, readonly) NSString *roomText;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000027@end
28
29@implementation ARDRoomTextField {
30 UITextField *_roomText;
31 UIButton *_clearButton;
32}
33
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000034- (instancetype)initWithFrame:(CGRect)frame {
35 if (self = [super initWithFrame:frame]) {
36 _roomText = [[UITextField alloc] initWithFrame:CGRectZero];
37 _roomText.borderStyle = UITextBorderStyleNone;
38 _roomText.font = [UIFont fontWithName:@"Roboto" size:12];
39 _roomText.placeholder = @"Room name";
hayscedd8fef2015-12-08 11:08:39 -080040 _roomText.autocorrectionType = UITextAutocorrectionTypeNo;
41 _roomText.autocapitalizationType = UITextAutocapitalizationTypeNone;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000042 _roomText.delegate = self;
43 [_roomText addTarget:self
44 action:@selector(textFieldDidChange:)
45 forControlEvents:UIControlEventEditingChanged];
46 [self addSubview:_roomText];
47
48 _clearButton = [UIButton buttonWithType:UIButtonTypeCustom];
49 UIImage *image = [UIImage imageForName:@"ic_clear_black_24dp.png"
50 color:[UIColor colorWithWhite:0 alpha:.4]];
51
52 [_clearButton setImage:image forState:UIControlStateNormal];
53 [_clearButton addTarget:self
54 action:@selector(onClear:)
55 forControlEvents:UIControlEventTouchUpInside];
56 _clearButton.hidden = YES;
57 [self addSubview:_clearButton];
58
59 // Give rounded corners and a light gray border.
60 self.layer.borderWidth = 1;
61 self.layer.borderColor = [[UIColor lightGrayColor] CGColor];
62 self.layer.cornerRadius = 2;
63 }
64 return self;
65}
66
67- (void)layoutSubviews {
68 CGRect bounds = self.bounds;
69 _clearButton.frame = CGRectMake(CGRectGetMaxX(bounds) - kRoomTextButtonSize,
70 CGRectGetMinY(bounds),
71 kRoomTextButtonSize,
72 kRoomTextButtonSize);
73 _roomText.frame = CGRectMake(
74 CGRectGetMinX(bounds) + kRoomTextFieldMargin,
75 CGRectGetMinY(bounds),
76 CGRectGetMinX(_clearButton.frame) - CGRectGetMinX(bounds) -
77 kRoomTextFieldMargin,
78 kRoomTextFieldHeight);
79}
80
81- (CGSize)sizeThatFits:(CGSize)size {
82 size.height = kRoomTextFieldHeight;
83 return size;
84}
85
haysc913e6452015-10-02 11:44:03 -070086- (NSString *)roomText {
87 return _roomText.text;
88}
89
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000090#pragma mark - UITextFieldDelegate
91
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000092- (BOOL)textFieldShouldReturn:(UITextField *)textField {
93 // There is no other control that can take focus, so manually resign focus
94 // when return (Join) is pressed to trigger |textFieldDidEndEditing|.
95 [textField resignFirstResponder];
96 return YES;
97}
98
99#pragma mark - Private
100
101- (void)textFieldDidChange:(id)sender {
102 [self updateClearButton];
103}
104
105- (void)onClear:(id)sender {
106 _roomText.text = @"";
107 [self updateClearButton];
108 [_roomText resignFirstResponder];
109}
110
111- (void)updateClearButton {
112 _clearButton.hidden = _roomText.text.length == 0;
113}
114
115@end
116
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000117@implementation ARDMainView {
118 UILabel *_appLabel;
119 ARDRoomTextField *_roomText;
haysc913e6452015-10-02 11:44:03 -0700120 UILabel *_callOptionsLabel;
121 UISwitch *_audioOnlySwitch;
122 UILabel *_audioOnlyLabel;
123 UISwitch *_loopbackSwitch;
124 UILabel *_loopbackLabel;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700125 UISwitch *_audioConfigDelaySwitch;
126 UILabel *_audioConfigDelayLabel;
haysc913e6452015-10-02 11:44:03 -0700127 UIButton *_startCallButton;
Zeke Chin615fabb2016-02-24 10:58:52 -0800128 UIButton *_audioLoopButton;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000129}
130
131@synthesize delegate = _delegate;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700132@synthesize isAudioLoopPlaying = _isAudioLoopPlaying;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000133
134- (instancetype)initWithFrame:(CGRect)frame {
135 if (self = [super initWithFrame:frame]) {
136 _appLabel = [[UILabel alloc] initWithFrame:CGRectZero];
137 _appLabel.text = @"AppRTCDemo";
138 _appLabel.font = [UIFont fontWithName:@"Roboto" size:34];
139 _appLabel.textColor = [UIColor colorWithWhite:0 alpha:.2];
140 [_appLabel sizeToFit];
141 [self addSubview:_appLabel];
142
143 _roomText = [[ARDRoomTextField alloc] initWithFrame:CGRectZero];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000144 [self addSubview:_roomText];
145
haysc913e6452015-10-02 11:44:03 -0700146 UIFont *controlFont = [UIFont fontWithName:@"Roboto" size:20];
147 UIColor *controlFontColor = [UIColor colorWithWhite:0 alpha:.6];
148
149 _callOptionsLabel = [[UILabel alloc] initWithFrame:CGRectZero];
150 _callOptionsLabel.text = @"Call Options";
151 _callOptionsLabel.font = controlFont;
152 _callOptionsLabel.textColor = controlFontColor;
153 [_callOptionsLabel sizeToFit];
154 [self addSubview:_callOptionsLabel];
155
156 _audioOnlySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
157 [_audioOnlySwitch sizeToFit];
158 [self addSubview:_audioOnlySwitch];
159
160 _audioOnlyLabel = [[UILabel alloc] initWithFrame:CGRectZero];
161 _audioOnlyLabel.text = @"Audio only";
162 _audioOnlyLabel.font = controlFont;
163 _audioOnlyLabel.textColor = controlFontColor;
164 [_audioOnlyLabel sizeToFit];
165 [self addSubview:_audioOnlyLabel];
166
167 _loopbackSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
168 [_loopbackSwitch sizeToFit];
169 [self addSubview:_loopbackSwitch];
170
171 _loopbackLabel = [[UILabel alloc] initWithFrame:CGRectZero];
172 _loopbackLabel.text = @"Loopback mode";
173 _loopbackLabel.font = controlFont;
174 _loopbackLabel.textColor = controlFontColor;
175 [_loopbackLabel sizeToFit];
176 [self addSubview:_loopbackLabel];
177
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700178 _audioConfigDelaySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
179 [_audioConfigDelaySwitch sizeToFit];
180 _audioConfigDelaySwitch.on = YES;
181 [self addSubview:_audioConfigDelaySwitch];
182
183 _audioConfigDelayLabel = [[UILabel alloc] initWithFrame:CGRectZero];
184 _audioConfigDelayLabel.text = @"Delay audio config";
185 _audioConfigDelayLabel.font = controlFont;
186 _audioConfigDelayLabel.textColor = controlFontColor;
187 [_audioConfigDelayLabel sizeToFit];
188 [self addSubview:_audioConfigDelayLabel];
189
haysc913e6452015-10-02 11:44:03 -0700190 _startCallButton = [UIButton buttonWithType:UIButtonTypeSystem];
191 _startCallButton.backgroundColor = [UIColor blueColor];
192 _startCallButton.layer.cornerRadius = 10;
193 _startCallButton.clipsToBounds = YES;
194 _startCallButton.contentEdgeInsets = UIEdgeInsetsMake(5, 10, 5, 10);
195 [_startCallButton setTitle:@"Start call"
196 forState:UIControlStateNormal];
197 _startCallButton.titleLabel.font = controlFont;
198 [_startCallButton setTitleColor:[UIColor whiteColor]
199 forState:UIControlStateNormal];
200 [_startCallButton setTitleColor:[UIColor lightGrayColor]
201 forState:UIControlStateSelected];
202 [_startCallButton sizeToFit];
203 [_startCallButton addTarget:self
204 action:@selector(onStartCall:)
205 forControlEvents:UIControlEventTouchUpInside];
206 [self addSubview:_startCallButton];
207
Zeke Chin615fabb2016-02-24 10:58:52 -0800208 // Used to test what happens to sounds when calls are in progress.
209 _audioLoopButton = [UIButton buttonWithType:UIButtonTypeSystem];
210 _audioLoopButton.layer.cornerRadius = 10;
211 _audioLoopButton.clipsToBounds = YES;
212 _audioLoopButton.contentEdgeInsets = UIEdgeInsetsMake(5, 10, 5, 10);
213 _audioLoopButton.titleLabel.font = controlFont;
214 [_audioLoopButton setTitleColor:[UIColor whiteColor]
215 forState:UIControlStateNormal];
216 [_audioLoopButton setTitleColor:[UIColor lightGrayColor]
217 forState:UIControlStateSelected];
218 [self updateAudioLoopButton];
219 [_audioLoopButton addTarget:self
220 action:@selector(onToggleAudioLoop:)
221 forControlEvents:UIControlEventTouchUpInside];
222 [self addSubview:_audioLoopButton];
223
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000224 self.backgroundColor = [UIColor whiteColor];
225 }
226 return self;
227}
228
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700229- (void)setIsAudioLoopPlaying:(BOOL)isAudioLoopPlaying {
230 if (_isAudioLoopPlaying == isAudioLoopPlaying) {
231 return;
232 }
233 _isAudioLoopPlaying = isAudioLoopPlaying;
234 [self updateAudioLoopButton];
235}
236
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000237- (void)layoutSubviews {
238 CGRect bounds = self.bounds;
239 CGFloat roomTextWidth = bounds.size.width - 2 * kRoomTextFieldMargin;
240 CGFloat roomTextHeight = [_roomText sizeThatFits:bounds.size].height;
241 _roomText.frame = CGRectMake(kRoomTextFieldMargin,
242 kStatusBarHeight + kRoomTextFieldMargin,
243 roomTextWidth,
244 roomTextHeight);
245 _appLabel.center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
haysc913e6452015-10-02 11:44:03 -0700246
247 CGFloat callOptionsLabelTop =
248 CGRectGetMaxY(_roomText.frame) + kCallControlMargin * 4;
249 _callOptionsLabel.frame = CGRectMake(kCallControlMargin,
250 callOptionsLabelTop,
251 _callOptionsLabel.frame.size.width,
252 _callOptionsLabel.frame.size.height);
253
254 CGFloat audioOnlyTop =
255 CGRectGetMaxY(_callOptionsLabel.frame) + kCallControlMargin * 2;
256 CGRect audioOnlyRect = CGRectMake(kCallControlMargin * 3,
257 audioOnlyTop,
258 _audioOnlySwitch.frame.size.width,
259 _audioOnlySwitch.frame.size.height);
260 _audioOnlySwitch.frame = audioOnlyRect;
261 CGFloat audioOnlyLabelCenterX = CGRectGetMaxX(audioOnlyRect) +
262 kCallControlMargin + _audioOnlyLabel.frame.size.width / 2;
263 _audioOnlyLabel.center = CGPointMake(audioOnlyLabelCenterX,
264 CGRectGetMidY(audioOnlyRect));
265
266 CGFloat loopbackModeTop =
267 CGRectGetMaxY(_audioOnlySwitch.frame) + kCallControlMargin;
268 CGRect loopbackModeRect = CGRectMake(kCallControlMargin * 3,
269 loopbackModeTop,
270 _loopbackSwitch.frame.size.width,
271 _loopbackSwitch.frame.size.height);
272 _loopbackSwitch.frame = loopbackModeRect;
273 CGFloat loopbackModeLabelCenterX = CGRectGetMaxX(loopbackModeRect) +
274 kCallControlMargin + _loopbackLabel.frame.size.width / 2;
275 _loopbackLabel.center = CGPointMake(loopbackModeLabelCenterX,
276 CGRectGetMidY(loopbackModeRect));
277
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700278 CGFloat audioConfigDelayTop =
279 CGRectGetMaxY(_loopbackSwitch.frame) + kCallControlMargin;
280 CGRect audioConfigDelayRect =
281 CGRectMake(kCallControlMargin * 3,
282 audioConfigDelayTop,
283 _audioConfigDelaySwitch.frame.size.width,
284 _audioConfigDelaySwitch.frame.size.height);
285 _audioConfigDelaySwitch.frame = audioConfigDelayRect;
286 CGFloat audioConfigDelayLabelCenterX = CGRectGetMaxX(audioConfigDelayRect) +
287 kCallControlMargin + _audioConfigDelayLabel.frame.size.width / 2;
288 _audioConfigDelayLabel.center =
289 CGPointMake(audioConfigDelayLabelCenterX,
290 CGRectGetMidY(audioConfigDelayRect));
291
Zeke Chin615fabb2016-02-24 10:58:52 -0800292 CGFloat audioLoopTop =
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700293 CGRectGetMaxY(audioConfigDelayRect) + kCallControlMargin * 3;
Zeke Chin615fabb2016-02-24 10:58:52 -0800294 _audioLoopButton.frame = CGRectMake(kCallControlMargin,
295 audioLoopTop,
296 _audioLoopButton.frame.size.width,
297 _audioLoopButton.frame.size.height);
298
299 CGFloat startCallTop =
300 CGRectGetMaxY(_audioLoopButton.frame) + kCallControlMargin * 3;
haysc913e6452015-10-02 11:44:03 -0700301 _startCallButton.frame = CGRectMake(kCallControlMargin,
302 startCallTop,
303 _startCallButton.frame.size.width,
304 _startCallButton.frame.size.height);
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000305}
306
haysc913e6452015-10-02 11:44:03 -0700307#pragma mark - Private
308
Zeke Chin615fabb2016-02-24 10:58:52 -0800309- (void)updateAudioLoopButton {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700310 if (_isAudioLoopPlaying) {
Zeke Chin615fabb2016-02-24 10:58:52 -0800311 _audioLoopButton.backgroundColor = [UIColor redColor];
312 [_audioLoopButton setTitle:@"Stop sound"
313 forState:UIControlStateNormal];
314 [_audioLoopButton sizeToFit];
315 } else {
316 _audioLoopButton.backgroundColor = [UIColor greenColor];
317 [_audioLoopButton setTitle:@"Play sound"
318 forState:UIControlStateNormal];
319 [_audioLoopButton sizeToFit];
320 }
321}
322
323- (void)onToggleAudioLoop:(id)sender {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700324 [_delegate mainViewDidToggleAudioLoop:self];
Zeke Chin615fabb2016-02-24 10:58:52 -0800325}
326
haysc913e6452015-10-02 11:44:03 -0700327- (void)onStartCall:(id)sender {
328 NSString *room = _roomText.roomText;
329 // If this is a loopback call, allow a generated room name.
330 if (!room.length && _loopbackSwitch.isOn) {
331 room = [[NSUUID UUID] UUIDString];
332 }
333 room = [room stringByReplacingOccurrencesOfString:@"-" withString:@""];
334 [_delegate mainView:self
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700335 didInputRoom:room
336 isLoopback:_loopbackSwitch.isOn
337 isAudioOnly:_audioOnlySwitch.isOn
338 shouldDelayAudioConfig:_audioConfigDelaySwitch.isOn];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000339}
340
341@end