From e150058236ea6b83b062c33cb09e1be126fd9424 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Thu, 15 Jun 2017 16:05:13 +0200 Subject: [PATCH] Move setting switches in AppRTCMobile to Settings screen All setting switches except "Loopback mode" is now in the Settings screen instead of the main screen. They are also persisted across app launches. Bug: webrtc:7748 Change-Id: Iafd84e5e39639770118e2503148d1bf7fb9c3d8d Reviewed-on: https://chromium-review.googlesource.com/527034 Commit-Queue: Magnus Jedvert Reviewed-by: Magnus Jedvert Cr-Commit-Position: refs/heads/master@{#18626} --- .../objc/AppRTCMobile/ARDAppClient+Internal.h | 3 - .../examples/objc/AppRTCMobile/ARDAppClient.h | 9 +- .../examples/objc/AppRTCMobile/ARDAppClient.m | 20 +-- .../objc/AppRTCMobile/ARDSettingsModel.h | 51 +++++++ .../objc/AppRTCMobile/ARDSettingsModel.m | 65 +++++++-- .../objc/AppRTCMobile/ARDSettingsStore.h | 17 +++ .../objc/AppRTCMobile/ARDSettingsStore.m | 61 ++++++++ .../objc/AppRTCMobile/ios/ARDMainView.h | 9 +- .../objc/AppRTCMobile/ios/ARDMainView.m | 117 +-------------- .../AppRTCMobile/ios/ARDMainViewController.m | 23 +-- .../ios/ARDSettingsViewController.m | 134 +++++++++++++++--- .../ios/ARDVideoCallViewController.h | 3 - .../ios/ARDVideoCallViewController.m | 10 +- .../AppRTCMobile/mac/APPRTCViewController.m | 5 +- .../AppRTCMobile/tests/ARDAppClient_xctest.mm | 30 ++-- .../tests/ARDSettingsModel_xctest.mm | 39 +++-- 16 files changed, 350 insertions(+), 246 deletions(-) diff --git a/webrtc/examples/objc/AppRTCMobile/ARDAppClient+Internal.h b/webrtc/examples/objc/AppRTCMobile/ARDAppClient+Internal.h index a21ac72aee..3cf40400f5 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDAppClient+Internal.h +++ b/webrtc/examples/objc/AppRTCMobile/ARDAppClient+Internal.h @@ -42,9 +42,6 @@ @property(nonatomic, strong) NSURL *webSocketURL; @property(nonatomic, strong) NSURL *webSocketRestURL; @property(nonatomic, readonly) BOOL isLoopback; -@property(nonatomic, readonly) BOOL isAudioOnly; -@property(nonatomic, readonly) BOOL shouldMakeAecDump; -@property(nonatomic, readonly) BOOL shouldUseLevelControl; @property(nonatomic, strong) RTCMediaConstraints *defaultPeerConnectionConstraints; diff --git a/webrtc/examples/objc/AppRTCMobile/ARDAppClient.h b/webrtc/examples/objc/AppRTCMobile/ARDAppClient.h index b613ec976f..8c27b345c6 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDAppClient.h +++ b/webrtc/examples/objc/AppRTCMobile/ARDAppClient.h @@ -70,16 +70,9 @@ typedef NS_ENUM(NSInteger, ARDAppClientState) { // Establishes a connection with the AppRTC servers for the given room id. // |settings| is an object containing settings such as video codec for the call. // If |isLoopback| is true, the call will connect to itself. -// If |isAudioOnly| is true, video will be disabled for the call. -// If |shouldMakeAecDump| is true, an aecdump will be created for the call. -// If |shouldUseLevelControl| is true, the level controller will be used -// in the call. - (void)connectToRoomWithId:(NSString *)roomId settings:(ARDSettingsModel *)settings - isLoopback:(BOOL)isLoopback - isAudioOnly:(BOOL)isAudioOnly - shouldMakeAecDump:(BOOL)shouldMakeAecDump - shouldUseLevelControl:(BOOL)shouldUseLevelControl; + isLoopback:(BOOL)isLoopback; // Disconnects from the AppRTC servers and any connected clients. - (void)disconnect; diff --git a/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m b/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m index 7e06612e6a..7e9fbdac75 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m +++ b/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m @@ -126,9 +126,6 @@ static int const kKbpsMultiplier = 1000; @synthesize defaultPeerConnectionConstraints = _defaultPeerConnectionConstraints; @synthesize isLoopback = _isLoopback; -@synthesize isAudioOnly = _isAudioOnly; -@synthesize shouldMakeAecDump = _shouldMakeAecDump; -@synthesize shouldUseLevelControl = _shouldUseLevelControl; - (instancetype)init { return [self initWithDelegate:nil]; @@ -214,17 +211,11 @@ static int const kKbpsMultiplier = 1000; - (void)connectToRoomWithId:(NSString *)roomId settings:(ARDSettingsModel *)settings - isLoopback:(BOOL)isLoopback - isAudioOnly:(BOOL)isAudioOnly - shouldMakeAecDump:(BOOL)shouldMakeAecDump - shouldUseLevelControl:(BOOL)shouldUseLevelControl { + isLoopback:(BOOL)isLoopback { NSParameterAssert(roomId.length); NSParameterAssert(_state == kARDAppClientStateDisconnected); _settings = settings; _isLoopback = isLoopback; - _isAudioOnly = isAudioOnly; - _shouldMakeAecDump = shouldMakeAecDump; - _shouldUseLevelControl = shouldUseLevelControl; self.state = kARDAppClientStateConnecting; #if defined(WEBRTC_IOS) @@ -569,7 +560,7 @@ static int const kKbpsMultiplier = 1000; } // Start aecdump diagnostic recording. - if (_shouldMakeAecDump) { + if ([_settings currentCreateAecDumpSettingFromStore]) { NSString *filePath = [self documentsFilePathForFileName:@"webrtc-audio.aecdump"]; if (![_factory startAecDumpWithFilePath:filePath maxSizeInBytes:kARDAppClientAecDumpMaxSizeInBytes]) { @@ -719,7 +710,7 @@ static int const kKbpsMultiplier = 1000; // support or emulation (http://goo.gl/rHAnC1) so don't bother // trying to open a local stream. #if !TARGET_IPHONE_SIMULATOR - if (!_isAudioOnly) { + if (![_settings currentAudioOnlySettingFromStore]) { RTCVideoSource *source = [_factory videoSource]; RTCCameraVideoCapturer *capturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:source]; [_delegate appClient:self didCreateLocalCapturer:capturer]; @@ -758,8 +749,9 @@ static int const kKbpsMultiplier = 1000; #pragma mark - Defaults - (RTCMediaConstraints *)defaultMediaAudioConstraints { - NSString *valueLevelControl = _shouldUseLevelControl ? - kRTCMediaConstraintsValueTrue : kRTCMediaConstraintsValueFalse; + NSString *valueLevelControl = [_settings currentUseLevelControllerSettingFromStore] ? + kRTCMediaConstraintsValueTrue : + kRTCMediaConstraintsValueFalse; NSDictionary *mandatoryConstraints = @{ kRTCMediaConstraintsLevelControl : valueLevelControl }; RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatoryConstraints diff --git a/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.h b/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.h index 0f07389b15..8b2679fa82 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.h +++ b/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.h @@ -11,6 +11,7 @@ #import NS_ASSUME_NONNULL_BEGIN + /** * Model class for user defined settings. * @@ -79,5 +80,55 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)storeMaxBitrateSetting:(nullable NSNumber *)bitrate; +/** + * Returns current audio only setting from store if present or default (NO) otherwise. + */ +- (BOOL)currentAudioOnlySettingFromStore; + +/** + * Stores the provided audio only setting into the store. + * + * @param setting the boolean value to be stored. + */ +- (void)storeAudioOnlySetting:(BOOL)audioOnly; + +/** + * Returns current create AecDump setting from store if present or default (NO) otherwise. + */ +- (BOOL)currentCreateAecDumpSettingFromStore; + +/** + * Stores the provided create AecDump setting into the store. + * + * @param setting the boolean value to be stored. + */ +- (void)storeCreateAecDumpSetting:(BOOL)createAecDump; + +/** + * Returns current setting whether to use level controller from store if present or default (NO) + * otherwise. + */ +- (BOOL)currentUseLevelControllerSettingFromStore; + +/** + * Stores the provided use level controller setting into the store. + * + * @param setting the boolean value to be stored. + */ +- (void)storeUseLevelControllerSetting:(BOOL)useLevelController; + +/** + * Returns current setting whether to use manual audio config from store if present or default (YES) + * otherwise. + */ +- (BOOL)currentUseManualAudioConfigSettingFromStore; + +/** + * Stores the provided use manual audio config setting into the store. + * + * @param setting the boolean value to be stored. + */ +- (void)storeUseManualAudioConfigSetting:(BOOL)useManualAudioConfig; + @end NS_ASSUME_NONNULL_END diff --git a/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.m b/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.m index 78d404a02d..0d3ca7ccb6 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.m +++ b/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.m @@ -56,13 +56,8 @@ static NSArray *videoCodecsStaticValues() { } - (NSString *)currentVideoResolutionSettingFromStore { - NSString *resolution = [[self settingsStore] videoResolution]; - if (!resolution) { - resolution = [self defaultVideoResolutionSetting]; - // To ensure consistency add the default to the store. - [[self settingsStore] setVideoResolution:resolution]; - } - return resolution; + [self registerStoreDefaults]; + return [[self settingsStore] videoResolution]; } - (BOOL)storeVideoResolutionSetting:(NSString *)resolution { @@ -78,12 +73,8 @@ static NSArray *videoCodecsStaticValues() { } - (NSString *)currentVideoCodecSettingFromStore { - NSString *videoCodec = [[self settingsStore] videoCodec]; - if (!videoCodec) { - videoCodec = [self defaultVideoCodecSetting]; - [[self settingsStore] setVideoCodec:videoCodec]; - } - return videoCodec; + [self registerStoreDefaults]; + return [[self settingsStore] videoCodec]; } - (BOOL)storeVideoCodecSetting:(NSString *)videoCodec { @@ -95,6 +86,7 @@ static NSArray *videoCodecsStaticValues() { } - (nullable NSNumber *)currentMaxBitrateSettingFromStore { + [self registerStoreDefaults]; return [[self settingsStore] maxBitrate]; } @@ -102,11 +94,44 @@ static NSArray *videoCodecsStaticValues() { [[self settingsStore] setMaxBitrate:bitrate]; } +- (BOOL)currentAudioOnlySettingFromStore { + return [[self settingsStore] audioOnly]; +} + +- (void)storeAudioOnlySetting:(BOOL)audioOnly { + [[self settingsStore] setAudioOnly:audioOnly]; +} + +- (BOOL)currentCreateAecDumpSettingFromStore { + return [[self settingsStore] createAecDump]; +} + +- (void)storeCreateAecDumpSetting:(BOOL)createAecDump { + [[self settingsStore] setCreateAecDump:createAecDump]; +} + +- (BOOL)currentUseLevelControllerSettingFromStore { + return [[self settingsStore] useLevelController]; +} + +- (void)storeUseLevelControllerSetting:(BOOL)useLevelController { + [[self settingsStore] setUseLevelController:useLevelController]; +} + +- (BOOL)currentUseManualAudioConfigSettingFromStore { + return [[self settingsStore] useManualAudioConfig]; +} + +- (void)storeUseManualAudioConfigSetting:(BOOL)useManualAudioConfig { + [[self settingsStore] setUseManualAudioConfig:useManualAudioConfig]; +} + #pragma mark - Testable - (ARDSettingsStore *)settingsStore { if (!_settingsStore) { _settingsStore = [[ARDSettingsStore alloc] init]; + [self registerStoreDefaults]; } return _settingsStore; } @@ -128,6 +153,10 @@ static NSArray *videoCodecsStaticValues() { return [self availableVideoResolutions][0]; } +- (NSString *)defaultVideoCodecSetting { + return videoCodecsStaticValues()[0]; +} + - (int)videoResolutionComponentAtIndex:(int)index inString:(NSString *)resolution { if (index != 0 && index != 1) { return 0; @@ -139,8 +168,14 @@ static NSArray *videoCodecsStaticValues() { return components[index].intValue; } -- (NSString *)defaultVideoCodecSetting { - return videoCodecsStaticValues()[0]; +- (void)registerStoreDefaults { + [ARDSettingsStore setDefaultsForVideoResolution:[self defaultVideoResolutionSetting] + videoCodec:[self defaultVideoCodecSetting] + bitrate:nil + audioOnly:NO + createAecDump:NO + useLevelController:NO + useManualAudioConfig:YES]; } @end diff --git a/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.h b/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.h index 3dd0f6431b..3f5f79106f 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.h +++ b/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.h @@ -19,6 +19,18 @@ NS_ASSUME_NONNULL_BEGIN */ @interface ARDSettingsStore : NSObject +/** + * Set fallback values in case the setting has not been written by the user. + * @param dictionary of values to store + */ ++ (void)setDefaultsForVideoResolution:(NSString *)videoResolution + videoCodec:(NSString *)videoCodec + bitrate:(nullable NSNumber *)bitrate + audioOnly:(BOOL)audioOnly + createAecDump:(BOOL)createAecDump + useLevelController:(BOOL)useLevelController + useManualAudioConfig:(BOOL)useManualAudioConfig; + @property(nonatomic) NSString *videoResolution; @property(nonatomic) NSString *videoCodec; @@ -33,5 +45,10 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)setMaxBitrate:(nullable NSNumber *)value; +@property(nonatomic) BOOL audioOnly; +@property(nonatomic) BOOL createAecDump; +@property(nonatomic) BOOL useLevelController; +@property(nonatomic) BOOL useManualAudioConfig; + @end NS_ASSUME_NONNULL_END diff --git a/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.m b/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.m index e25b28860c..8ccc438800 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.m +++ b/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.m @@ -13,6 +13,10 @@ static NSString *const kVideoResolutionKey = @"rtc_video_resolution_key"; static NSString *const kVideoCodecKey = @"rtc_video_codec_key"; static NSString *const kBitrateKey = @"rtc_max_bitrate_key"; +static NSString *const kAudioOnlyKey = @"rtc_audio_only_key"; +static NSString *const kCreateAecDumpKey = @"rtc_create_aec_dump_key"; +static NSString *const kUseLevelControllerKey = @"rtc_use_level_controller_key"; +static NSString *const kUseManualAudioConfigKey = @"rtc_use_manual_audio_config_key"; NS_ASSUME_NONNULL_BEGIN @interface ARDSettingsStore () { @@ -23,6 +27,27 @@ NS_ASSUME_NONNULL_BEGIN @implementation ARDSettingsStore ++ (void)setDefaultsForVideoResolution:(NSString *)videoResolution + videoCodec:(NSString *)videoCodec + bitrate:(nullable NSNumber *)bitrate + audioOnly:(BOOL)audioOnly + createAecDump:(BOOL)createAecDump + useLevelController:(BOOL)useLevelController + useManualAudioConfig:(BOOL)useManualAudioConfig { + NSMutableDictionary *defaultsDictionary = [@{ + kVideoResolutionKey : videoResolution, + kVideoCodecKey : videoCodec, + kAudioOnlyKey : @(audioOnly), + kCreateAecDumpKey : @(createAecDump), + kUseLevelControllerKey : @(useLevelController), + kUseManualAudioConfigKey : @(useManualAudioConfig) + } mutableCopy]; + if (bitrate) { + [defaultsDictionary setObject:bitrate forKey:kBitrateKey]; + } + [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDictionary]; +} + - (NSUserDefaults *)storage { if (!_storage) { _storage = [NSUserDefaults standardUserDefaults]; @@ -57,5 +82,41 @@ NS_ASSUME_NONNULL_BEGIN [self.storage synchronize]; } +- (BOOL)audioOnly { + return [self.storage boolForKey:kAudioOnlyKey]; +} + +- (void)setAudioOnly:(BOOL)audioOnly { + [self.storage setBool:audioOnly forKey:kAudioOnlyKey]; + [self.storage synchronize]; +} + +- (BOOL)createAecDump { + return [self.storage boolForKey:kCreateAecDumpKey]; +} + +- (void)setCreateAecDump:(BOOL)createAecDump { + [self.storage setBool:createAecDump forKey:kCreateAecDumpKey]; + [self.storage synchronize]; +} + +- (BOOL)useLevelController { + return [self.storage boolForKey:kUseLevelControllerKey]; +} + +- (void)setUseLevelController:(BOOL)useLevelController { + [self.storage setBool:useLevelController forKey:kUseLevelControllerKey]; + [self.storage synchronize]; +} + +- (BOOL)useManualAudioConfig { + return [self.storage boolForKey:kUseManualAudioConfigKey]; +} + +- (void)setUseManualAudioConfig:(BOOL)useManualAudioConfig { + [self.storage setBool:useManualAudioConfig forKey:kUseManualAudioConfigKey]; + [self.storage synchronize]; +} + @end NS_ASSUME_NONNULL_END diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDMainView.h b/webrtc/examples/objc/AppRTCMobile/ios/ARDMainView.h index 1f2497a1e2..c6691c2d84 100644 --- a/webrtc/examples/objc/AppRTCMobile/ios/ARDMainView.h +++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDMainView.h @@ -14,14 +14,7 @@ @protocol ARDMainViewDelegate -- (void)mainView:(ARDMainView *)mainView - didInputRoom:(NSString *)room - isLoopback:(BOOL)isLoopback - isAudioOnly:(BOOL)isAudioOnly - shouldMakeAecDump:(BOOL)shouldMakeAecDump - shouldUseLevelControl:(BOOL)shouldUseLevelControl - useManualAudio:(BOOL)useManualAudio; - +- (void)mainView:(ARDMainView *)mainView didInputRoom:(NSString *)room isLoopback:(BOOL)isLoopback; - (void)mainViewDidToggleAudioLoop:(ARDMainView *)mainView; @end diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDMainView.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDMainView.m index 0308ea0cfd..fcce3c3015 100644 --- a/webrtc/examples/objc/AppRTCMobile/ios/ARDMainView.m +++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDMainView.m @@ -74,16 +74,8 @@ static CGFloat const kCallControlMargin = 8; @implementation ARDMainView { ARDRoomTextField *_roomText; UILabel *_callOptionsLabel; - UISwitch *_audioOnlySwitch; - UILabel *_audioOnlyLabel; - UISwitch *_aecdumpSwitch; - UILabel *_aecdumpLabel; - UISwitch *_levelControlSwitch; - UILabel *_levelControlLabel; UISwitch *_loopbackSwitch; UILabel *_loopbackLabel; - UISwitch *_useManualAudioSwitch; - UILabel *_useManualAudioLabel; UIButton *_startCallButton; UIButton *_audioLoopButton; } @@ -106,17 +98,6 @@ static CGFloat const kCallControlMargin = 8; [_callOptionsLabel sizeToFit]; [self addSubview:_callOptionsLabel]; - _audioOnlySwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; - [_audioOnlySwitch sizeToFit]; - [self addSubview:_audioOnlySwitch]; - - _audioOnlyLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - _audioOnlyLabel.text = @"Audio only"; - _audioOnlyLabel.font = controlFont; - _audioOnlyLabel.textColor = controlFontColor; - [_audioOnlyLabel sizeToFit]; - [self addSubview:_audioOnlyLabel]; - _loopbackSwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; [_loopbackSwitch sizeToFit]; [self addSubview:_loopbackSwitch]; @@ -128,40 +109,6 @@ static CGFloat const kCallControlMargin = 8; [_loopbackLabel sizeToFit]; [self addSubview:_loopbackLabel]; - _aecdumpSwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; - [_aecdumpSwitch sizeToFit]; - [self addSubview:_aecdumpSwitch]; - - _aecdumpLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - _aecdumpLabel.text = @"Create AecDump"; - _aecdumpLabel.font = controlFont; - _aecdumpLabel.textColor = controlFontColor; - [_aecdumpLabel sizeToFit]; - [self addSubview:_aecdumpLabel]; - - _levelControlSwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; - [_levelControlSwitch sizeToFit]; - [self addSubview:_levelControlSwitch]; - - _levelControlLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - _levelControlLabel.text = @"Use level controller"; - _levelControlLabel.font = controlFont; - _levelControlLabel.textColor = controlFontColor; - [_levelControlLabel sizeToFit]; - [self addSubview:_levelControlLabel]; - - _useManualAudioSwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; - [_useManualAudioSwitch sizeToFit]; - _useManualAudioSwitch.on = YES; - [self addSubview:_useManualAudioSwitch]; - - _useManualAudioLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - _useManualAudioLabel.text = @"Use manual audio config"; - _useManualAudioLabel.font = controlFont; - _useManualAudioLabel.textColor = controlFontColor; - [_useManualAudioLabel sizeToFit]; - [self addSubview:_useManualAudioLabel]; - _startCallButton = [UIButton buttonWithType:UIButtonTypeSystem]; [_startCallButton setTitle:@"Start call" forState:UIControlStateNormal]; @@ -208,20 +155,7 @@ static CGFloat const kCallControlMargin = 8; _callOptionsLabel.frame.size.width, _callOptionsLabel.frame.size.height); - CGFloat audioOnlyTop = - CGRectGetMaxY(_callOptionsLabel.frame) + kCallControlMargin * 2; - CGRect audioOnlyRect = CGRectMake(kCallControlMargin * 3, - audioOnlyTop, - _audioOnlySwitch.frame.size.width, - _audioOnlySwitch.frame.size.height); - _audioOnlySwitch.frame = audioOnlyRect; - CGFloat audioOnlyLabelCenterX = CGRectGetMaxX(audioOnlyRect) + - kCallControlMargin + _audioOnlyLabel.frame.size.width / 2; - _audioOnlyLabel.center = CGPointMake(audioOnlyLabelCenterX, - CGRectGetMidY(audioOnlyRect)); - - CGFloat loopbackModeTop = - CGRectGetMaxY(_audioOnlySwitch.frame) + kCallControlMargin; + CGFloat loopbackModeTop = CGRectGetMaxY(_callOptionsLabel.frame) + kCallControlMargin * 2; CGRect loopbackModeRect = CGRectMake(kCallControlMargin * 3, loopbackModeTop, _loopbackSwitch.frame.size.width, @@ -232,46 +166,7 @@ static CGFloat const kCallControlMargin = 8; _loopbackLabel.center = CGPointMake(loopbackModeLabelCenterX, CGRectGetMidY(loopbackModeRect)); - CGFloat aecdumpModeTop = - CGRectGetMaxY(_loopbackSwitch.frame) + kCallControlMargin; - CGRect aecdumpModeRect = CGRectMake(kCallControlMargin * 3, - aecdumpModeTop, - _aecdumpSwitch.frame.size.width, - _aecdumpSwitch.frame.size.height); - _aecdumpSwitch.frame = aecdumpModeRect; - CGFloat aecdumpModeLabelCenterX = CGRectGetMaxX(aecdumpModeRect) + - kCallControlMargin + _aecdumpLabel.frame.size.width / 2; - _aecdumpLabel.center = CGPointMake(aecdumpModeLabelCenterX, - CGRectGetMidY(aecdumpModeRect)); - - CGFloat levelControlModeTop = - CGRectGetMaxY(_aecdumpSwitch.frame) + kCallControlMargin; - CGRect levelControlModeRect = CGRectMake(kCallControlMargin * 3, - levelControlModeTop, - _levelControlSwitch.frame.size.width, - _levelControlSwitch.frame.size.height); - _levelControlSwitch.frame = levelControlModeRect; - CGFloat levelControlModeLabelCenterX = CGRectGetMaxX(levelControlModeRect) + - kCallControlMargin + _levelControlLabel.frame.size.width / 2; - _levelControlLabel.center = CGPointMake(levelControlModeLabelCenterX, - CGRectGetMidY(levelControlModeRect)); - - CGFloat useManualAudioTop = - CGRectGetMaxY(_levelControlSwitch.frame) + kCallControlMargin; - CGRect useManualAudioRect = - CGRectMake(kCallControlMargin * 3, - useManualAudioTop, - _useManualAudioSwitch.frame.size.width, - _useManualAudioSwitch.frame.size.height); - _useManualAudioSwitch.frame = useManualAudioRect; - CGFloat useManualAudioLabelCenterX = CGRectGetMaxX(useManualAudioRect) + - kCallControlMargin + _useManualAudioLabel.frame.size.width / 2; - _useManualAudioLabel.center = - CGPointMake(useManualAudioLabelCenterX, - CGRectGetMidY(useManualAudioRect)); - - CGFloat audioLoopTop = - CGRectGetMaxY(useManualAudioRect) + kCallControlMargin * 3; + CGFloat audioLoopTop = CGRectGetMaxY(loopbackModeRect) + kCallControlMargin * 3; _audioLoopButton.frame = CGRectMake(kCallControlMargin, audioLoopTop, _audioLoopButton.frame.size.width, @@ -304,13 +199,7 @@ static CGFloat const kCallControlMargin = 8; } - (void)onStartCall:(id)sender { - [_delegate mainView:self - didInputRoom:_roomText.roomText - isLoopback:_loopbackSwitch.isOn - isAudioOnly:_audioOnlySwitch.isOn - shouldMakeAecDump:_aecdumpSwitch.isOn - shouldUseLevelControl:_levelControlSwitch.isOn - useManualAudio:_useManualAudioSwitch.isOn]; + [_delegate mainView:self didInputRoom:_roomText.roomText isLoopback:_loopbackSwitch.isOn]; } @end diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDMainViewController.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDMainViewController.m index 0e93aae9ad..c57dace7a7 100644 --- a/webrtc/examples/objc/AppRTCMobile/ios/ARDMainViewController.m +++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDMainViewController.m @@ -44,13 +44,7 @@ static NSString *const loopbackLaunchProcessArgument = @"loopback"; - (void)viewDidLoad { [super viewDidLoad]; if ([[[NSProcessInfo processInfo] arguments] containsObject:loopbackLaunchProcessArgument]) { - [self mainView:nil - didInputRoom:@"" - isLoopback:YES - isAudioOnly:NO - shouldMakeAecDump:NO - shouldUseLevelControl:NO - useManualAudio:NO]; + [self mainView:nil didInputRoom:@"" isLoopback:YES]; } } @@ -91,13 +85,7 @@ static NSString *const loopbackLaunchProcessArgument = @"loopback"; #pragma mark - ARDMainViewDelegate -- (void)mainView:(ARDMainView *)mainView - didInputRoom:(NSString *)room - isLoopback:(BOOL)isLoopback - isAudioOnly:(BOOL)isAudioOnly - shouldMakeAecDump:(BOOL)shouldMakeAecDump - shouldUseLevelControl:(BOOL)shouldUseLevelControl - useManualAudio:(BOOL)useManualAudio { +- (void)mainView:(ARDMainView *)mainView didInputRoom:(NSString *)room isLoopback:(BOOL)isLoopback { if (!room.length) { if (isLoopback) { // If this is a loopback call, allow a generated room name. @@ -132,17 +120,16 @@ static NSString *const loopbackLaunchProcessArgument = @"loopback"; return; } + ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init]; + RTCAudioSession *session = [RTCAudioSession sharedInstance]; - session.useManualAudio = useManualAudio; + session.useManualAudio = [settingsModel currentUseManualAudioConfigSettingFromStore]; session.isAudioEnabled = NO; // Kick off the video call. ARDVideoCallViewController *videoCallViewController = [[ARDVideoCallViewController alloc] initForRoom:trimmedRoom isLoopback:isLoopback - isAudioOnly:isAudioOnly - shouldMakeAecDump:shouldMakeAecDump - shouldUseLevelControl:shouldUseLevelControl delegate:self]; videoCallViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m index 09a3d6d744..fce5df7117 100644 --- a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m +++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m @@ -14,11 +14,19 @@ NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(int, ARDSettingsSections) { - ARDSettingsSectionVideoResolution = 0, + ARDSettingsSectionAudioSettings = 0, + ARDSettingsSectionVideoResolution, ARDSettingsSectionVideoCodec, ARDSettingsSectionBitRate, }; +typedef NS_ENUM(int, ARDAudioSettingsOptions) { + ARDAudioSettingsAudioOnly = 0, + ARDAudioSettingsCreateAecDump, + ARDAudioSettingsUseLevelController, + ARDAudioSettingsUseManualAudioConfig, +}; + @interface ARDSettingsViewController () { ARDSettingsModel *_settingsModel; } @@ -46,22 +54,16 @@ typedef NS_ENUM(int, ARDSettingsSections) { - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - [self addCheckmarkInSection:ARDSettingsSectionVideoResolution - withArray:[self videoResolutionArray] - selecting:[_settingsModel currentVideoResolutionSettingFromStore]]; - [self addCheckmarkInSection:ARDSettingsSectionVideoCodec - withArray:[self videoCodecArray] - selecting:[_settingsModel currentVideoCodecSettingFromStore]]; } #pragma mark - Data source - (NSArray *)videoResolutionArray { - return _settingsModel.availableVideoResolutions; + return [_settingsModel availableVideoResolutions]; } - (NSArray *)videoCodecArray { - return _settingsModel.availableVideoCodecs; + return [_settingsModel availableVideoCodecs]; } #pragma mark - @@ -74,16 +76,6 @@ typedef NS_ENUM(int, ARDSettingsSections) { self.navigationItem.leftBarButtonItem = barItem; } -- (void)addCheckmarkInSection:(int)section - withArray:(NSArray*) array - selecting:(NSString*)selection { - NSUInteger indexOfSelection = [array indexOfObject:selection]; - NSIndexPath *pathToBeDecorated = [NSIndexPath indexPathForRow:indexOfSelection - inSection:section]; - UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:pathToBeDecorated]; - cell.accessoryType = UITableViewCellAccessoryCheckmark; -} - #pragma mark - Dismissal of view controller - (void)dismissModally:(id)sender { @@ -93,11 +85,13 @@ typedef NS_ENUM(int, ARDSettingsSections) { #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 3; + return 4; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { switch (section) { + case ARDSettingsSectionAudioSettings: + return 4; case ARDSettingsSectionVideoResolution: return self.videoResolutionArray.count; case ARDSettingsSectionVideoCodec: @@ -133,6 +127,8 @@ updateListSelectionAtIndexPath:(NSIndexPath *)indexPath - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { switch (section) { + case ARDSettingsSectionAudioSettings: + return @"Audio"; case ARDSettingsSectionVideoResolution: return @"Video resolution"; case ARDSettingsSectionVideoCodec: @@ -147,6 +143,9 @@ updateListSelectionAtIndexPath:(NSIndexPath *)indexPath - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { switch (indexPath.section) { + case ARDSettingsSectionAudioSettings: + return [self audioSettingsTableViewCellForTableView:tableView atIndexPath:indexPath]; + case ARDSettingsSectionVideoResolution: return [self videoResolutionTableViewCellForTableView:tableView atIndexPath:indexPath]; @@ -184,7 +183,14 @@ updateListSelectionAtIndexPath:(NSIndexPath *)indexPath cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:dequeueIdentifier]; } - cell.textLabel.text = self.videoResolutionArray[indexPath.row]; + NSString *resolution = self.videoResolutionArray[indexPath.row]; + cell.textLabel.text = resolution; + if ([resolution isEqualToString:[_settingsModel currentVideoResolutionSettingFromStore]]) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + } else { + cell.accessoryType = UITableViewCellAccessoryNone; + } + return cell; } @@ -208,7 +214,13 @@ updateListSelectionAtIndexPath:(NSIndexPath *)indexPath cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:dequeueIdentifier]; } - cell.textLabel.text = self.videoCodecArray[indexPath.row]; + NSString *codec = self.videoCodecArray[indexPath.row]; + cell.textLabel.text = codec; + if ([codec isEqualToString:[_settingsModel currentVideoCodecSettingFromStore]]) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + } else { + cell.accessoryType = UITableViewCellAccessoryNone; + } return cell; } @@ -275,5 +287,83 @@ updateListSelectionAtIndexPath:(NSIndexPath *)indexPath [_settingsModel storeMaxBitrateSetting:bitrateNumber]; } +#pragma mark - Table view delegate(Audio settings) + +- (UITableViewCell *)audioSettingsTableViewCellForTableView:(UITableView *)tableView + atIndexPath:(NSIndexPath *)indexPath { + NSString *dequeueIdentifier = @"ARDSettingsAudioSettingsCellIdentifier"; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier]; + if (!cell) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:dequeueIdentifier]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectZero]; + switchView.tag = indexPath.row; + [switchView addTarget:self + action:@selector(audioSettingSwitchChanged:) + forControlEvents:UIControlEventValueChanged]; + cell.accessoryView = switchView; + } + + cell.textLabel.text = [self labelForAudioSettingAtIndexPathRow:indexPath.row]; + UISwitch *switchView = (UISwitch *)cell.accessoryView; + switchView.on = [self valueForAudioSettingAtIndexPathRow:indexPath.row]; + + return cell; +} + +- (NSString *)labelForAudioSettingAtIndexPathRow:(NSInteger)setting { + switch (setting) { + case ARDAudioSettingsAudioOnly: + return @"Audio only"; + case ARDAudioSettingsCreateAecDump: + return @"Create AecDump"; + case ARDAudioSettingsUseLevelController: + return @"Use level controller"; + case ARDAudioSettingsUseManualAudioConfig: + return @"Use manual audio config"; + default: + return @""; + } +} + +- (BOOL)valueForAudioSettingAtIndexPathRow:(NSInteger)setting { + switch (setting) { + case ARDAudioSettingsAudioOnly: + return [_settingsModel currentAudioOnlySettingFromStore]; + case ARDAudioSettingsCreateAecDump: + return [_settingsModel currentCreateAecDumpSettingFromStore]; + case ARDAudioSettingsUseLevelController: + return [_settingsModel currentUseLevelControllerSettingFromStore]; + case ARDAudioSettingsUseManualAudioConfig: + return [_settingsModel currentUseManualAudioConfigSettingFromStore]; + default: + return NO; + } +} + +- (void)audioSettingSwitchChanged:(UISwitch *)sender { + switch (sender.tag) { + case ARDAudioSettingsAudioOnly: { + [_settingsModel storeAudioOnlySetting:sender.isOn]; + break; + } + case ARDAudioSettingsCreateAecDump: { + [_settingsModel storeCreateAecDumpSetting:sender.isOn]; + break; + } + case ARDAudioSettingsUseLevelController: { + [_settingsModel storeUseLevelControllerSetting:sender.isOn]; + break; + } + case ARDAudioSettingsUseManualAudioConfig: { + [_settingsModel storeUseManualAudioConfigSetting:sender.isOn]; + break; + } + default: + break; + } +} + @end NS_ASSUME_NONNULL_END diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.h b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.h index 3ca2dc2e9a..bdb8747524 100644 --- a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.h +++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.h @@ -23,9 +23,6 @@ - (instancetype)initForRoom:(NSString *)room isLoopback:(BOOL)isLoopback - isAudioOnly:(BOOL)isAudioOnly - shouldMakeAecDump:(BOOL)shouldMakeAecDump - shouldUseLevelControl:(BOOL)shouldUseLevelControl delegate:(id)delegate; @end diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m index fd33e01e71..03ce626266 100644 --- a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m +++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m @@ -40,21 +40,13 @@ - (instancetype)initForRoom:(NSString *)room isLoopback:(BOOL)isLoopback - isAudioOnly:(BOOL)isAudioOnly - shouldMakeAecDump:(BOOL)shouldMakeAecDump - shouldUseLevelControl:(BOOL)shouldUseLevelControl delegate:(id)delegate { if (self = [super init]) { ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init]; _delegate = delegate; _client = [[ARDAppClient alloc] initWithDelegate:self]; - [_client connectToRoomWithId:room - settings:settingsModel - isLoopback:isLoopback - isAudioOnly:isAudioOnly - shouldMakeAecDump:shouldMakeAecDump - shouldUseLevelControl:shouldUseLevelControl]; + [_client connectToRoomWithId:room settings:settingsModel isLoopback:isLoopback]; } return self; } diff --git a/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m b/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m index ab65b7e6d9..cb82e88888 100644 --- a/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m +++ b/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m @@ -402,10 +402,7 @@ static NSUInteger const kBottomViewHeight = 200; ARDAppClient* client = [[ARDAppClient alloc] initWithDelegate:self]; [client connectToRoomWithId:roomId settings:[[ARDSettingsModel alloc] init] // Use default settings. - isLoopback:isLoopback - isAudioOnly:NO - shouldMakeAecDump:NO - shouldUseLevelControl:NO]; + isLoopback:isLoopback]; _client = client; } diff --git a/webrtc/examples/objc/AppRTCMobile/tests/ARDAppClient_xctest.mm b/webrtc/examples/objc/AppRTCMobile/tests/ARDAppClient_xctest.mm index fc7b76822c..b1ce5f0c59 100644 --- a/webrtc/examples/objc/AppRTCMobile/tests/ARDAppClient_xctest.mm +++ b/webrtc/examples/objc/AppRTCMobile/tests/ARDAppClient_xctest.mm @@ -116,6 +116,15 @@ return mockTURNClient; } +- (id)mockSettingsModel { + ARDSettingsModel *model = [[ARDSettingsModel alloc] init]; + id partialMock = [OCMockObject partialMockForObject:model]; + [[[partialMock stub] andReturn:@[ @"640x480", @"960x540", @"1280x720" ]] + availableVideoResolutions]; + + return model; +} + - (ARDAppClient *)createAppClientForRoomId:(NSString *)roomId clientId:(NSString *)clientId isInitiator:(BOOL)isInitiator @@ -209,18 +218,8 @@ weakAnswerer = answerer; // Kick off connection. - [caller connectToRoomWithId:roomId - settings:[[ARDSettingsModel alloc] init] - isLoopback:NO - isAudioOnly:NO - shouldMakeAecDump:NO - shouldUseLevelControl:NO]; - [answerer connectToRoomWithId:roomId - settings:[[ARDSettingsModel alloc] init] - isLoopback:NO - isAudioOnly:NO - shouldMakeAecDump:NO - shouldUseLevelControl:NO]; + [caller connectToRoomWithId:roomId settings:[self mockSettingsModel] isLoopback:NO]; + [answerer connectToRoomWithId:roomId settings:[self mockSettingsModel] isLoopback:NO]; [self waitForExpectationsWithTimeout:20 handler:^(NSError *error) { if (error) { XCTFail(@"Expectation failed with error %@.", error); @@ -253,11 +252,8 @@ // Kick off connection. [caller connectToRoomWithId:roomId - settings:[[ARDSettingsModel alloc] init] - isLoopback:NO - isAudioOnly:NO - shouldMakeAecDump:NO - shouldUseLevelControl:NO]; + settings:[self mockSettingsModel] + isLoopback:NO]; [self waitForExpectationsWithTimeout:20 handler:^(NSError *error) { if (error) { XCTFail("Expectation timed out with error: %@.", error); diff --git a/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm b/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm index b139b97e73..b44f9358ac 100644 --- a/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm +++ b/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm @@ -25,9 +25,8 @@ @implementation ARDSettingsModelTests -- (id)setupMockStoreWithVideoResolution:(NSString *)videoResolution { +- (id)setupMockStore { id storeMock = [OCMockObject mockForClass:[ARDSettingsStore class]]; - [([[storeMock stub] andReturn:videoResolution])videoResolution]; id partialMock = [OCMockObject partialMockForObject:_model]; [[[partialMock stub] andReturn:storeMock] settingsStore]; @@ -41,39 +40,57 @@ _model = [[ARDSettingsModel alloc] init]; } -- (void)testDefaultMediaFromStore { - id storeMock = [self setupMockStoreWithVideoResolution:nil]; - [[storeMock expect] setVideoResolution:@"640x480"]; - +- (void)testRetrievingSetting { + id storeMock = [self setupMockStore]; + [[[storeMock expect] andReturn:@"640x480"] videoResolution]; NSString *string = [_model currentVideoResolutionSettingFromStore]; XCTAssertEqualObjects(string, @"640x480"); - [storeMock verify]; } - (void)testStoringInvalidConstraintReturnsNo { - __unused id storeMock = [self setupMockStoreWithVideoResolution:@"960x480"]; + id storeMock = [self setupMockStore]; + [([[storeMock stub] andReturn:@"960x480"])videoResolution]; XCTAssertFalse([_model storeVideoResolutionSetting:@"960x480"]); } - (void)testWidthConstraintFromStore { - [self setupMockStoreWithVideoResolution:@"1270x480"]; + id storeMock = [self setupMockStore]; + [([[storeMock stub] andReturn:@"1270x480"])videoResolution]; int width = [_model currentVideoResolutionWidthFromStore]; XCTAssertEqual(width, 1270); } - (void)testHeightConstraintFromStore { - [self setupMockStoreWithVideoResolution:@"960x540"]; + id storeMock = [self setupMockStore]; + [([[storeMock stub] andReturn:@"960x540"])videoResolution]; int height = [_model currentVideoResolutionHeightFromStore]; XCTAssertEqual(height, 540); } - (void)testConstraintComponentIsNilWhenInvalidConstraintString { - [self setupMockStoreWithVideoResolution:@"invalid"]; + id storeMock = [self setupMockStore]; + [([[storeMock stub] andReturn:@"invalid"])videoResolution]; int width = [_model currentVideoResolutionWidthFromStore]; XCTAssertEqual(width, 0); } + +- (void)testStoringAudioSetting { + id storeMock = [self setupMockStore]; + [[storeMock expect] setAudioOnly:YES]; + + [_model storeAudioOnlySetting:YES]; + [storeMock verify]; +} + +- (void)testReturningDefaultCallOption { + id storeMock = [self setupMockStore]; + [[[storeMock stub] andReturnValue:@YES] useManualAudioConfig]; + + XCTAssertTrue([_model currentUseManualAudioConfigSettingFromStore]); +} + @end