blob: 59b428a3037eddb596923ffa1edefcbc7c5a519e [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 +000022
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000023// Helper view that contains a text field and a clear button.
24@interface ARDRoomTextField : UIView <UITextFieldDelegate>
haysc913e6452015-10-02 11:44:03 -070025@property(nonatomic, readonly) NSString *roomText;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000026@end
27
28@implementation ARDRoomTextField {
29 UITextField *_roomText;
30 UIButton *_clearButton;
31}
32
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000033- (instancetype)initWithFrame:(CGRect)frame {
34 if (self = [super initWithFrame:frame]) {
35 _roomText = [[UITextField alloc] initWithFrame:CGRectZero];
36 _roomText.borderStyle = UITextBorderStyleNone;
37 _roomText.font = [UIFont fontWithName:@"Roboto" size:12];
38 _roomText.placeholder = @"Room name";
hayscedd8fef2015-12-08 11:08:39 -080039 _roomText.autocorrectionType = UITextAutocorrectionTypeNo;
40 _roomText.autocapitalizationType = UITextAutocapitalizationTypeNone;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000041 _roomText.delegate = self;
42 [_roomText addTarget:self
43 action:@selector(textFieldDidChange:)
44 forControlEvents:UIControlEventEditingChanged];
45 [self addSubview:_roomText];
46
47 _clearButton = [UIButton buttonWithType:UIButtonTypeCustom];
48 UIImage *image = [UIImage imageForName:@"ic_clear_black_24dp.png"
49 color:[UIColor colorWithWhite:0 alpha:.4]];
50
51 [_clearButton setImage:image forState:UIControlStateNormal];
52 [_clearButton addTarget:self
53 action:@selector(onClear:)
54 forControlEvents:UIControlEventTouchUpInside];
55 _clearButton.hidden = YES;
56 [self addSubview:_clearButton];
57
58 // Give rounded corners and a light gray border.
59 self.layer.borderWidth = 1;
60 self.layer.borderColor = [[UIColor lightGrayColor] CGColor];
61 self.layer.cornerRadius = 2;
62 }
63 return self;
64}
65
66- (void)layoutSubviews {
67 CGRect bounds = self.bounds;
68 _clearButton.frame = CGRectMake(CGRectGetMaxX(bounds) - kRoomTextButtonSize,
69 CGRectGetMinY(bounds),
70 kRoomTextButtonSize,
71 kRoomTextButtonSize);
72 _roomText.frame = CGRectMake(
73 CGRectGetMinX(bounds) + kRoomTextFieldMargin,
74 CGRectGetMinY(bounds),
75 CGRectGetMinX(_clearButton.frame) - CGRectGetMinX(bounds) -
76 kRoomTextFieldMargin,
77 kRoomTextFieldHeight);
78}
79
80- (CGSize)sizeThatFits:(CGSize)size {
81 size.height = kRoomTextFieldHeight;
82 return size;
83}
84
haysc913e6452015-10-02 11:44:03 -070085- (NSString *)roomText {
86 return _roomText.text;
87}
88
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000089#pragma mark - UITextFieldDelegate
90
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000091- (BOOL)textFieldShouldReturn:(UITextField *)textField {
92 // There is no other control that can take focus, so manually resign focus
93 // when return (Join) is pressed to trigger |textFieldDidEndEditing|.
94 [textField resignFirstResponder];
95 return YES;
96}
97
98#pragma mark - Private
99
100- (void)textFieldDidChange:(id)sender {
101 [self updateClearButton];
102}
103
104- (void)onClear:(id)sender {
105 _roomText.text = @"";
106 [self updateClearButton];
107 [_roomText resignFirstResponder];
108}
109
110- (void)updateClearButton {
111 _clearButton.hidden = _roomText.text.length == 0;
112}
113
114@end
115
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000116@implementation ARDMainView {
117 UILabel *_appLabel;
118 ARDRoomTextField *_roomText;
haysc913e6452015-10-02 11:44:03 -0700119 UILabel *_callOptionsLabel;
120 UISwitch *_audioOnlySwitch;
121 UILabel *_audioOnlyLabel;
peah5085b0c2016-08-25 22:15:14 -0700122 UISwitch *_aecdumpSwitch;
123 UILabel *_aecdumpLabel;
haysc913e6452015-10-02 11:44:03 -0700124 UISwitch *_loopbackSwitch;
125 UILabel *_loopbackLabel;
tkchind2511962016-05-06 18:54:15 -0700126 UISwitch *_useManualAudioSwitch;
127 UILabel *_useManualAudioLabel;
haysc913e6452015-10-02 11:44:03 -0700128 UIButton *_startCallButton;
Zeke Chin615fabb2016-02-24 10:58:52 -0800129 UIButton *_audioLoopButton;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000130}
131
132@synthesize delegate = _delegate;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700133@synthesize isAudioLoopPlaying = _isAudioLoopPlaying;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000134
135- (instancetype)initWithFrame:(CGRect)frame {
136 if (self = [super initWithFrame:frame]) {
137 _appLabel = [[UILabel alloc] initWithFrame:CGRectZero];
138 _appLabel.text = @"AppRTCDemo";
139 _appLabel.font = [UIFont fontWithName:@"Roboto" size:34];
140 _appLabel.textColor = [UIColor colorWithWhite:0 alpha:.2];
141 [_appLabel sizeToFit];
142 [self addSubview:_appLabel];
143
144 _roomText = [[ARDRoomTextField alloc] initWithFrame:CGRectZero];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000145 [self addSubview:_roomText];
146
haysc913e6452015-10-02 11:44:03 -0700147 UIFont *controlFont = [UIFont fontWithName:@"Roboto" size:20];
148 UIColor *controlFontColor = [UIColor colorWithWhite:0 alpha:.6];
149
150 _callOptionsLabel = [[UILabel alloc] initWithFrame:CGRectZero];
151 _callOptionsLabel.text = @"Call Options";
152 _callOptionsLabel.font = controlFont;
153 _callOptionsLabel.textColor = controlFontColor;
154 [_callOptionsLabel sizeToFit];
155 [self addSubview:_callOptionsLabel];
156
157 _audioOnlySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
158 [_audioOnlySwitch sizeToFit];
159 [self addSubview:_audioOnlySwitch];
160
161 _audioOnlyLabel = [[UILabel alloc] initWithFrame:CGRectZero];
162 _audioOnlyLabel.text = @"Audio only";
163 _audioOnlyLabel.font = controlFont;
164 _audioOnlyLabel.textColor = controlFontColor;
165 [_audioOnlyLabel sizeToFit];
166 [self addSubview:_audioOnlyLabel];
167
168 _loopbackSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
169 [_loopbackSwitch sizeToFit];
170 [self addSubview:_loopbackSwitch];
171
172 _loopbackLabel = [[UILabel alloc] initWithFrame:CGRectZero];
173 _loopbackLabel.text = @"Loopback mode";
174 _loopbackLabel.font = controlFont;
175 _loopbackLabel.textColor = controlFontColor;
176 [_loopbackLabel sizeToFit];
177 [self addSubview:_loopbackLabel];
178
peah5085b0c2016-08-25 22:15:14 -0700179 _aecdumpSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
180 [_aecdumpSwitch sizeToFit];
181 [self addSubview:_aecdumpSwitch];
182
183 _aecdumpLabel = [[UILabel alloc] initWithFrame:CGRectZero];
184 _aecdumpLabel.text = @"Create AecDump";
185 _aecdumpLabel.font = controlFont;
186 _aecdumpLabel.textColor = controlFontColor;
187 [_aecdumpLabel sizeToFit];
188 [self addSubview:_aecdumpLabel];
189
tkchind2511962016-05-06 18:54:15 -0700190 _useManualAudioSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
191 [_useManualAudioSwitch sizeToFit];
192 _useManualAudioSwitch.on = YES;
193 [self addSubview:_useManualAudioSwitch];
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700194
tkchind2511962016-05-06 18:54:15 -0700195 _useManualAudioLabel = [[UILabel alloc] initWithFrame:CGRectZero];
196 _useManualAudioLabel.text = @"Use manual audio config";
197 _useManualAudioLabel.font = controlFont;
198 _useManualAudioLabel.textColor = controlFontColor;
199 [_useManualAudioLabel sizeToFit];
200 [self addSubview:_useManualAudioLabel];
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700201
haysc913e6452015-10-02 11:44:03 -0700202 _startCallButton = [UIButton buttonWithType:UIButtonTypeSystem];
203 _startCallButton.backgroundColor = [UIColor blueColor];
204 _startCallButton.layer.cornerRadius = 10;
205 _startCallButton.clipsToBounds = YES;
206 _startCallButton.contentEdgeInsets = UIEdgeInsetsMake(5, 10, 5, 10);
207 [_startCallButton setTitle:@"Start call"
208 forState:UIControlStateNormal];
209 _startCallButton.titleLabel.font = controlFont;
210 [_startCallButton setTitleColor:[UIColor whiteColor]
211 forState:UIControlStateNormal];
212 [_startCallButton setTitleColor:[UIColor lightGrayColor]
213 forState:UIControlStateSelected];
214 [_startCallButton sizeToFit];
215 [_startCallButton addTarget:self
216 action:@selector(onStartCall:)
217 forControlEvents:UIControlEventTouchUpInside];
218 [self addSubview:_startCallButton];
219
Zeke Chin615fabb2016-02-24 10:58:52 -0800220 // Used to test what happens to sounds when calls are in progress.
221 _audioLoopButton = [UIButton buttonWithType:UIButtonTypeSystem];
222 _audioLoopButton.layer.cornerRadius = 10;
223 _audioLoopButton.clipsToBounds = YES;
224 _audioLoopButton.contentEdgeInsets = UIEdgeInsetsMake(5, 10, 5, 10);
225 _audioLoopButton.titleLabel.font = controlFont;
226 [_audioLoopButton setTitleColor:[UIColor whiteColor]
227 forState:UIControlStateNormal];
228 [_audioLoopButton setTitleColor:[UIColor lightGrayColor]
229 forState:UIControlStateSelected];
230 [self updateAudioLoopButton];
231 [_audioLoopButton addTarget:self
232 action:@selector(onToggleAudioLoop:)
233 forControlEvents:UIControlEventTouchUpInside];
234 [self addSubview:_audioLoopButton];
235
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000236 self.backgroundColor = [UIColor whiteColor];
237 }
238 return self;
239}
240
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700241- (void)setIsAudioLoopPlaying:(BOOL)isAudioLoopPlaying {
242 if (_isAudioLoopPlaying == isAudioLoopPlaying) {
243 return;
244 }
245 _isAudioLoopPlaying = isAudioLoopPlaying;
246 [self updateAudioLoopButton];
247}
248
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000249- (void)layoutSubviews {
250 CGRect bounds = self.bounds;
251 CGFloat roomTextWidth = bounds.size.width - 2 * kRoomTextFieldMargin;
252 CGFloat roomTextHeight = [_roomText sizeThatFits:bounds.size].height;
253 _roomText.frame = CGRectMake(kRoomTextFieldMargin,
254 kStatusBarHeight + kRoomTextFieldMargin,
255 roomTextWidth,
256 roomTextHeight);
257 _appLabel.center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
haysc913e6452015-10-02 11:44:03 -0700258
259 CGFloat callOptionsLabelTop =
260 CGRectGetMaxY(_roomText.frame) + kCallControlMargin * 4;
261 _callOptionsLabel.frame = CGRectMake(kCallControlMargin,
262 callOptionsLabelTop,
263 _callOptionsLabel.frame.size.width,
264 _callOptionsLabel.frame.size.height);
265
266 CGFloat audioOnlyTop =
267 CGRectGetMaxY(_callOptionsLabel.frame) + kCallControlMargin * 2;
268 CGRect audioOnlyRect = CGRectMake(kCallControlMargin * 3,
269 audioOnlyTop,
270 _audioOnlySwitch.frame.size.width,
271 _audioOnlySwitch.frame.size.height);
272 _audioOnlySwitch.frame = audioOnlyRect;
273 CGFloat audioOnlyLabelCenterX = CGRectGetMaxX(audioOnlyRect) +
274 kCallControlMargin + _audioOnlyLabel.frame.size.width / 2;
275 _audioOnlyLabel.center = CGPointMake(audioOnlyLabelCenterX,
276 CGRectGetMidY(audioOnlyRect));
277
278 CGFloat loopbackModeTop =
279 CGRectGetMaxY(_audioOnlySwitch.frame) + kCallControlMargin;
280 CGRect loopbackModeRect = CGRectMake(kCallControlMargin * 3,
281 loopbackModeTop,
282 _loopbackSwitch.frame.size.width,
283 _loopbackSwitch.frame.size.height);
284 _loopbackSwitch.frame = loopbackModeRect;
285 CGFloat loopbackModeLabelCenterX = CGRectGetMaxX(loopbackModeRect) +
286 kCallControlMargin + _loopbackLabel.frame.size.width / 2;
287 _loopbackLabel.center = CGPointMake(loopbackModeLabelCenterX,
288 CGRectGetMidY(loopbackModeRect));
289
peah5085b0c2016-08-25 22:15:14 -0700290 CGFloat aecdumpModeTop =
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700291 CGRectGetMaxY(_loopbackSwitch.frame) + kCallControlMargin;
peah5085b0c2016-08-25 22:15:14 -0700292 CGRect aecdumpModeRect = CGRectMake(kCallControlMargin * 3,
293 aecdumpModeTop,
294 _aecdumpSwitch.frame.size.width,
295 _aecdumpSwitch.frame.size.height);
296 _aecdumpSwitch.frame = aecdumpModeRect;
297 CGFloat aecdumpModeLabelCenterX = CGRectGetMaxX(aecdumpModeRect) +
298 kCallControlMargin + _aecdumpLabel.frame.size.width / 2;
299 _aecdumpLabel.center = CGPointMake(aecdumpModeLabelCenterX,
300 CGRectGetMidY(aecdumpModeRect));
301
302
303 CGFloat useManualAudioTop =
304 CGRectGetMaxY(_aecdumpSwitch.frame) + kCallControlMargin;
tkchind2511962016-05-06 18:54:15 -0700305 CGRect useManualAudioRect =
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700306 CGRectMake(kCallControlMargin * 3,
tkchind2511962016-05-06 18:54:15 -0700307 useManualAudioTop,
308 _useManualAudioSwitch.frame.size.width,
309 _useManualAudioSwitch.frame.size.height);
310 _useManualAudioSwitch.frame = useManualAudioRect;
311 CGFloat useManualAudioLabelCenterX = CGRectGetMaxX(useManualAudioRect) +
312 kCallControlMargin + _useManualAudioLabel.frame.size.width / 2;
313 _useManualAudioLabel.center =
314 CGPointMake(useManualAudioLabelCenterX,
315 CGRectGetMidY(useManualAudioRect));
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700316
Zeke Chin615fabb2016-02-24 10:58:52 -0800317 CGFloat audioLoopTop =
tkchind2511962016-05-06 18:54:15 -0700318 CGRectGetMaxY(useManualAudioRect) + kCallControlMargin * 3;
Zeke Chin615fabb2016-02-24 10:58:52 -0800319 _audioLoopButton.frame = CGRectMake(kCallControlMargin,
320 audioLoopTop,
321 _audioLoopButton.frame.size.width,
322 _audioLoopButton.frame.size.height);
323
324 CGFloat startCallTop =
325 CGRectGetMaxY(_audioLoopButton.frame) + kCallControlMargin * 3;
haysc913e6452015-10-02 11:44:03 -0700326 _startCallButton.frame = CGRectMake(kCallControlMargin,
327 startCallTop,
328 _startCallButton.frame.size.width,
329 _startCallButton.frame.size.height);
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000330}
331
haysc913e6452015-10-02 11:44:03 -0700332#pragma mark - Private
333
Zeke Chin615fabb2016-02-24 10:58:52 -0800334- (void)updateAudioLoopButton {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700335 if (_isAudioLoopPlaying) {
Zeke Chin615fabb2016-02-24 10:58:52 -0800336 _audioLoopButton.backgroundColor = [UIColor redColor];
337 [_audioLoopButton setTitle:@"Stop sound"
338 forState:UIControlStateNormal];
339 [_audioLoopButton sizeToFit];
340 } else {
341 _audioLoopButton.backgroundColor = [UIColor greenColor];
342 [_audioLoopButton setTitle:@"Play sound"
343 forState:UIControlStateNormal];
344 [_audioLoopButton sizeToFit];
345 }
346}
347
348- (void)onToggleAudioLoop:(id)sender {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700349 [_delegate mainViewDidToggleAudioLoop:self];
Zeke Chin615fabb2016-02-24 10:58:52 -0800350}
351
haysc913e6452015-10-02 11:44:03 -0700352- (void)onStartCall:(id)sender {
353 NSString *room = _roomText.roomText;
354 // If this is a loopback call, allow a generated room name.
355 if (!room.length && _loopbackSwitch.isOn) {
356 room = [[NSUUID UUID] UUIDString];
357 }
358 room = [room stringByReplacingOccurrencesOfString:@"-" withString:@""];
359 [_delegate mainView:self
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700360 didInputRoom:room
361 isLoopback:_loopbackSwitch.isOn
362 isAudioOnly:_audioOnlySwitch.isOn
peah5085b0c2016-08-25 22:15:14 -0700363 shouldMakeAecDump:_aecdumpSwitch.isOn
tkchind2511962016-05-06 18:54:15 -0700364 useManualAudio:_useManualAudioSwitch.isOn];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000365}
366
367@end