blob: 20340366c5cf7f003fd145385fc5f4fe0166866a [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 {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000117 ARDRoomTextField *_roomText;
haysc913e6452015-10-02 11:44:03 -0700118 UILabel *_callOptionsLabel;
119 UISwitch *_audioOnlySwitch;
120 UILabel *_audioOnlyLabel;
peah5085b0c2016-08-25 22:15:14 -0700121 UISwitch *_aecdumpSwitch;
122 UILabel *_aecdumpLabel;
tkchinab1293a2016-08-30 12:35:05 -0700123 UISwitch *_levelControlSwitch;
124 UILabel *_levelControlLabel;
haysc913e6452015-10-02 11:44:03 -0700125 UISwitch *_loopbackSwitch;
126 UILabel *_loopbackLabel;
tkchind2511962016-05-06 18:54:15 -0700127 UISwitch *_useManualAudioSwitch;
128 UILabel *_useManualAudioLabel;
haysc913e6452015-10-02 11:44:03 -0700129 UIButton *_startCallButton;
Zeke Chin615fabb2016-02-24 10:58:52 -0800130 UIButton *_audioLoopButton;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000131}
132
133@synthesize delegate = _delegate;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700134@synthesize isAudioLoopPlaying = _isAudioLoopPlaying;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000135
136- (instancetype)initWithFrame:(CGRect)frame {
137 if (self = [super initWithFrame:frame]) {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000138 _roomText = [[ARDRoomTextField alloc] initWithFrame:CGRectZero];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000139 [self addSubview:_roomText];
140
haysc913e6452015-10-02 11:44:03 -0700141 UIFont *controlFont = [UIFont fontWithName:@"Roboto" size:20];
142 UIColor *controlFontColor = [UIColor colorWithWhite:0 alpha:.6];
143
144 _callOptionsLabel = [[UILabel alloc] initWithFrame:CGRectZero];
145 _callOptionsLabel.text = @"Call Options";
146 _callOptionsLabel.font = controlFont;
147 _callOptionsLabel.textColor = controlFontColor;
148 [_callOptionsLabel sizeToFit];
149 [self addSubview:_callOptionsLabel];
150
151 _audioOnlySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
152 [_audioOnlySwitch sizeToFit];
153 [self addSubview:_audioOnlySwitch];
154
155 _audioOnlyLabel = [[UILabel alloc] initWithFrame:CGRectZero];
156 _audioOnlyLabel.text = @"Audio only";
157 _audioOnlyLabel.font = controlFont;
158 _audioOnlyLabel.textColor = controlFontColor;
159 [_audioOnlyLabel sizeToFit];
160 [self addSubview:_audioOnlyLabel];
161
162 _loopbackSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
163 [_loopbackSwitch sizeToFit];
164 [self addSubview:_loopbackSwitch];
165
166 _loopbackLabel = [[UILabel alloc] initWithFrame:CGRectZero];
167 _loopbackLabel.text = @"Loopback mode";
168 _loopbackLabel.font = controlFont;
169 _loopbackLabel.textColor = controlFontColor;
170 [_loopbackLabel sizeToFit];
171 [self addSubview:_loopbackLabel];
172
peah5085b0c2016-08-25 22:15:14 -0700173 _aecdumpSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
174 [_aecdumpSwitch sizeToFit];
175 [self addSubview:_aecdumpSwitch];
176
177 _aecdumpLabel = [[UILabel alloc] initWithFrame:CGRectZero];
178 _aecdumpLabel.text = @"Create AecDump";
179 _aecdumpLabel.font = controlFont;
180 _aecdumpLabel.textColor = controlFontColor;
181 [_aecdumpLabel sizeToFit];
182 [self addSubview:_aecdumpLabel];
183
tkchinab1293a2016-08-30 12:35:05 -0700184 _levelControlSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
185 [_levelControlSwitch sizeToFit];
186 [self addSubview:_levelControlSwitch];
187
188 _levelControlLabel = [[UILabel alloc] initWithFrame:CGRectZero];
189 _levelControlLabel.text = @"Use level controller";
190 _levelControlLabel.font = controlFont;
191 _levelControlLabel.textColor = controlFontColor;
192 [_levelControlLabel sizeToFit];
193 [self addSubview:_levelControlLabel];
194
tkchind2511962016-05-06 18:54:15 -0700195 _useManualAudioSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
196 [_useManualAudioSwitch sizeToFit];
197 _useManualAudioSwitch.on = YES;
198 [self addSubview:_useManualAudioSwitch];
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700199
tkchind2511962016-05-06 18:54:15 -0700200 _useManualAudioLabel = [[UILabel alloc] initWithFrame:CGRectZero];
201 _useManualAudioLabel.text = @"Use manual audio config";
202 _useManualAudioLabel.font = controlFont;
203 _useManualAudioLabel.textColor = controlFontColor;
204 [_useManualAudioLabel sizeToFit];
205 [self addSubview:_useManualAudioLabel];
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700206
haysc913e6452015-10-02 11:44:03 -0700207 _startCallButton = [UIButton buttonWithType:UIButtonTypeSystem];
208 _startCallButton.backgroundColor = [UIColor blueColor];
209 _startCallButton.layer.cornerRadius = 10;
210 _startCallButton.clipsToBounds = YES;
211 _startCallButton.contentEdgeInsets = UIEdgeInsetsMake(5, 10, 5, 10);
212 [_startCallButton setTitle:@"Start call"
213 forState:UIControlStateNormal];
214 _startCallButton.titleLabel.font = controlFont;
215 [_startCallButton setTitleColor:[UIColor whiteColor]
216 forState:UIControlStateNormal];
217 [_startCallButton setTitleColor:[UIColor lightGrayColor]
218 forState:UIControlStateSelected];
219 [_startCallButton sizeToFit];
220 [_startCallButton addTarget:self
221 action:@selector(onStartCall:)
222 forControlEvents:UIControlEventTouchUpInside];
223 [self addSubview:_startCallButton];
224
Zeke Chin615fabb2016-02-24 10:58:52 -0800225 // Used to test what happens to sounds when calls are in progress.
226 _audioLoopButton = [UIButton buttonWithType:UIButtonTypeSystem];
227 _audioLoopButton.layer.cornerRadius = 10;
228 _audioLoopButton.clipsToBounds = YES;
229 _audioLoopButton.contentEdgeInsets = UIEdgeInsetsMake(5, 10, 5, 10);
230 _audioLoopButton.titleLabel.font = controlFont;
231 [_audioLoopButton setTitleColor:[UIColor whiteColor]
232 forState:UIControlStateNormal];
233 [_audioLoopButton setTitleColor:[UIColor lightGrayColor]
234 forState:UIControlStateSelected];
235 [self updateAudioLoopButton];
236 [_audioLoopButton addTarget:self
237 action:@selector(onToggleAudioLoop:)
238 forControlEvents:UIControlEventTouchUpInside];
239 [self addSubview:_audioLoopButton];
240
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000241 self.backgroundColor = [UIColor whiteColor];
242 }
243 return self;
244}
245
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700246- (void)setIsAudioLoopPlaying:(BOOL)isAudioLoopPlaying {
247 if (_isAudioLoopPlaying == isAudioLoopPlaying) {
248 return;
249 }
250 _isAudioLoopPlaying = isAudioLoopPlaying;
251 [self updateAudioLoopButton];
252}
253
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000254- (void)layoutSubviews {
255 CGRect bounds = self.bounds;
256 CGFloat roomTextWidth = bounds.size.width - 2 * kRoomTextFieldMargin;
257 CGFloat roomTextHeight = [_roomText sizeThatFits:bounds.size].height;
denicija6d6762c2016-10-28 04:53:16 -0700258 _roomText.frame =
259 CGRectMake(kRoomTextFieldMargin, kRoomTextFieldMargin, roomTextWidth, roomTextHeight);
haysc913e6452015-10-02 11:44:03 -0700260
261 CGFloat callOptionsLabelTop =
262 CGRectGetMaxY(_roomText.frame) + kCallControlMargin * 4;
263 _callOptionsLabel.frame = CGRectMake(kCallControlMargin,
264 callOptionsLabelTop,
265 _callOptionsLabel.frame.size.width,
266 _callOptionsLabel.frame.size.height);
267
268 CGFloat audioOnlyTop =
269 CGRectGetMaxY(_callOptionsLabel.frame) + kCallControlMargin * 2;
270 CGRect audioOnlyRect = CGRectMake(kCallControlMargin * 3,
271 audioOnlyTop,
272 _audioOnlySwitch.frame.size.width,
273 _audioOnlySwitch.frame.size.height);
274 _audioOnlySwitch.frame = audioOnlyRect;
275 CGFloat audioOnlyLabelCenterX = CGRectGetMaxX(audioOnlyRect) +
276 kCallControlMargin + _audioOnlyLabel.frame.size.width / 2;
277 _audioOnlyLabel.center = CGPointMake(audioOnlyLabelCenterX,
278 CGRectGetMidY(audioOnlyRect));
279
280 CGFloat loopbackModeTop =
281 CGRectGetMaxY(_audioOnlySwitch.frame) + kCallControlMargin;
282 CGRect loopbackModeRect = CGRectMake(kCallControlMargin * 3,
283 loopbackModeTop,
284 _loopbackSwitch.frame.size.width,
285 _loopbackSwitch.frame.size.height);
286 _loopbackSwitch.frame = loopbackModeRect;
287 CGFloat loopbackModeLabelCenterX = CGRectGetMaxX(loopbackModeRect) +
288 kCallControlMargin + _loopbackLabel.frame.size.width / 2;
289 _loopbackLabel.center = CGPointMake(loopbackModeLabelCenterX,
290 CGRectGetMidY(loopbackModeRect));
291
peah5085b0c2016-08-25 22:15:14 -0700292 CGFloat aecdumpModeTop =
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700293 CGRectGetMaxY(_loopbackSwitch.frame) + kCallControlMargin;
peah5085b0c2016-08-25 22:15:14 -0700294 CGRect aecdumpModeRect = CGRectMake(kCallControlMargin * 3,
295 aecdumpModeTop,
296 _aecdumpSwitch.frame.size.width,
297 _aecdumpSwitch.frame.size.height);
298 _aecdumpSwitch.frame = aecdumpModeRect;
299 CGFloat aecdumpModeLabelCenterX = CGRectGetMaxX(aecdumpModeRect) +
300 kCallControlMargin + _aecdumpLabel.frame.size.width / 2;
301 _aecdumpLabel.center = CGPointMake(aecdumpModeLabelCenterX,
302 CGRectGetMidY(aecdumpModeRect));
303
tkchinab1293a2016-08-30 12:35:05 -0700304 CGFloat levelControlModeTop =
305 CGRectGetMaxY(_aecdumpSwitch.frame) + kCallControlMargin;
306 CGRect levelControlModeRect = CGRectMake(kCallControlMargin * 3,
307 levelControlModeTop,
308 _levelControlSwitch.frame.size.width,
309 _levelControlSwitch.frame.size.height);
310 _levelControlSwitch.frame = levelControlModeRect;
311 CGFloat levelControlModeLabelCenterX = CGRectGetMaxX(levelControlModeRect) +
312 kCallControlMargin + _levelControlLabel.frame.size.width / 2;
313 _levelControlLabel.center = CGPointMake(levelControlModeLabelCenterX,
314 CGRectGetMidY(levelControlModeRect));
peah5085b0c2016-08-25 22:15:14 -0700315
316 CGFloat useManualAudioTop =
tkchinab1293a2016-08-30 12:35:05 -0700317 CGRectGetMaxY(_levelControlSwitch.frame) + kCallControlMargin;
tkchind2511962016-05-06 18:54:15 -0700318 CGRect useManualAudioRect =
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700319 CGRectMake(kCallControlMargin * 3,
tkchind2511962016-05-06 18:54:15 -0700320 useManualAudioTop,
321 _useManualAudioSwitch.frame.size.width,
322 _useManualAudioSwitch.frame.size.height);
323 _useManualAudioSwitch.frame = useManualAudioRect;
324 CGFloat useManualAudioLabelCenterX = CGRectGetMaxX(useManualAudioRect) +
325 kCallControlMargin + _useManualAudioLabel.frame.size.width / 2;
326 _useManualAudioLabel.center =
327 CGPointMake(useManualAudioLabelCenterX,
328 CGRectGetMidY(useManualAudioRect));
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700329
Zeke Chin615fabb2016-02-24 10:58:52 -0800330 CGFloat audioLoopTop =
tkchind2511962016-05-06 18:54:15 -0700331 CGRectGetMaxY(useManualAudioRect) + kCallControlMargin * 3;
Zeke Chin615fabb2016-02-24 10:58:52 -0800332 _audioLoopButton.frame = CGRectMake(kCallControlMargin,
333 audioLoopTop,
334 _audioLoopButton.frame.size.width,
335 _audioLoopButton.frame.size.height);
336
337 CGFloat startCallTop =
338 CGRectGetMaxY(_audioLoopButton.frame) + kCallControlMargin * 3;
haysc913e6452015-10-02 11:44:03 -0700339 _startCallButton.frame = CGRectMake(kCallControlMargin,
340 startCallTop,
341 _startCallButton.frame.size.width,
342 _startCallButton.frame.size.height);
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000343}
344
haysc913e6452015-10-02 11:44:03 -0700345#pragma mark - Private
346
Zeke Chin615fabb2016-02-24 10:58:52 -0800347- (void)updateAudioLoopButton {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700348 if (_isAudioLoopPlaying) {
Zeke Chin615fabb2016-02-24 10:58:52 -0800349 _audioLoopButton.backgroundColor = [UIColor redColor];
350 [_audioLoopButton setTitle:@"Stop sound"
351 forState:UIControlStateNormal];
352 [_audioLoopButton sizeToFit];
353 } else {
354 _audioLoopButton.backgroundColor = [UIColor greenColor];
355 [_audioLoopButton setTitle:@"Play sound"
356 forState:UIControlStateNormal];
357 [_audioLoopButton sizeToFit];
358 }
359}
360
361- (void)onToggleAudioLoop:(id)sender {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700362 [_delegate mainViewDidToggleAudioLoop:self];
Zeke Chin615fabb2016-02-24 10:58:52 -0800363}
364
haysc913e6452015-10-02 11:44:03 -0700365- (void)onStartCall:(id)sender {
366 NSString *room = _roomText.roomText;
367 // If this is a loopback call, allow a generated room name.
368 if (!room.length && _loopbackSwitch.isOn) {
369 room = [[NSUUID UUID] UUIDString];
370 }
371 room = [room stringByReplacingOccurrencesOfString:@"-" withString:@""];
372 [_delegate mainView:self
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700373 didInputRoom:room
374 isLoopback:_loopbackSwitch.isOn
375 isAudioOnly:_audioOnlySwitch.isOn
peah5085b0c2016-08-25 22:15:14 -0700376 shouldMakeAecDump:_aecdumpSwitch.isOn
tkchinab1293a2016-08-30 12:35:05 -0700377 shouldUseLevelControl:_levelControlSwitch.isOn
tkchind2511962016-05-06 18:54:15 -0700378 useManualAudio:_useManualAudioSwitch.isOn];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000379}
380
381@end