ARDSettingsViewController.m (12755B)
1 /* 2 * Copyright 2016 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 "ARDSettingsViewController.h" 12 #import "ARDSettingsModel.h" 13 #import "RTCVideoCodecInfo+HumanReadable.h" 14 15 NS_ASSUME_NONNULL_BEGIN 16 17 typedef NS_ENUM(int, ARDSettingsSections) { 18 ARDSettingsSectionAudioSettings = 0, 19 ARDSettingsSectionVideoResolution, 20 ARDSettingsSectionVideoCodec, 21 ARDSettingsSectionBitRate, 22 }; 23 24 typedef NS_ENUM(int, ARDAudioSettingsOptions) { 25 ARDAudioSettingsAudioOnly = 0, 26 ARDAudioSettingsCreateAecDump, 27 ARDAudioSettingsUseManualAudioConfig, 28 }; 29 30 @interface ARDSettingsViewController () <UITextFieldDelegate> { 31 ARDSettingsModel *_settingsModel; 32 } 33 34 @end 35 36 @implementation ARDSettingsViewController 37 38 - (instancetype)initWithStyle:(UITableViewStyle)style 39 settingsModel:(ARDSettingsModel *)settingsModel { 40 self = [super initWithStyle:style]; 41 if (self) { 42 _settingsModel = settingsModel; 43 } 44 return self; 45 } 46 47 #pragma mark - View lifecycle 48 49 - (void)viewDidLoad { 50 [super viewDidLoad]; 51 self.title = @"Settings"; 52 [self addDoneBarButton]; 53 } 54 55 - (void)viewWillAppear:(BOOL)animated { 56 [super viewWillAppear:animated]; 57 } 58 59 #pragma mark - Data source 60 61 - (NSArray<NSString *> *)videoResolutionArray { 62 return [_settingsModel availableVideoResolutions]; 63 } 64 65 - (NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *)videoCodecArray { 66 return [_settingsModel availableVideoCodecs]; 67 } 68 69 #pragma mark - 70 71 - (void)addDoneBarButton { 72 UIBarButtonItem *barItem = [[UIBarButtonItem alloc] 73 initWithBarButtonSystemItem:UIBarButtonSystemItemDone 74 target:self 75 action:@selector(dismissModally:)]; 76 self.navigationItem.leftBarButtonItem = barItem; 77 } 78 79 #pragma mark - Dismissal of view controller 80 81 - (void)dismissModally:(id)sender { 82 [self dismissViewControllerAnimated:YES completion:nil]; 83 } 84 85 #pragma mark - Table view data source 86 87 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 88 return 4; 89 } 90 91 - (NSInteger)tableView:(UITableView *)tableView 92 numberOfRowsInSection:(NSInteger)section { 93 switch (section) { 94 case ARDSettingsSectionAudioSettings: 95 return 3; 96 case ARDSettingsSectionVideoResolution: 97 return self.videoResolutionArray.count; 98 case ARDSettingsSectionVideoCodec: 99 return self.videoCodecArray.count; 100 default: 101 return 1; 102 } 103 } 104 105 #pragma mark - Table view delegate helpers 106 107 - (void)removeAllAccessories:(UITableView *)tableView inSection:(int)section { 108 for (int i = 0; i < [tableView numberOfRowsInSection:section]; i++) { 109 NSIndexPath *rowPath = [NSIndexPath indexPathForRow:i inSection:section]; 110 UITableViewCell *cell = [tableView cellForRowAtIndexPath:rowPath]; 111 cell.accessoryType = UITableViewCellAccessoryNone; 112 } 113 } 114 115 - (void)tableView:(UITableView *)tableView 116 updateListSelectionAtIndexPath:(NSIndexPath *)indexPath 117 inSection:(int)section { 118 [self removeAllAccessories:tableView inSection:section]; 119 UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 120 cell.accessoryType = UITableViewCellAccessoryCheckmark; 121 [tableView deselectRowAtIndexPath:indexPath animated:YES]; 122 } 123 124 #pragma mark - Table view delegate 125 126 - (nullable NSString *)tableView:(UITableView *)tableView 127 titleForHeaderInSection:(NSInteger)section { 128 switch (section) { 129 case ARDSettingsSectionAudioSettings: 130 return @"Audio"; 131 case ARDSettingsSectionVideoResolution: 132 return @"Video resolution"; 133 case ARDSettingsSectionVideoCodec: 134 return @"Video codec"; 135 case ARDSettingsSectionBitRate: 136 return @"Maximum bitrate"; 137 default: 138 return @""; 139 } 140 } 141 142 - (UITableViewCell *)tableView:(UITableView *)tableView 143 cellForRowAtIndexPath:(NSIndexPath *)indexPath { 144 switch (indexPath.section) { 145 case ARDSettingsSectionAudioSettings: 146 return [self audioSettingsTableViewCellForTableView:tableView 147 atIndexPath:indexPath]; 148 149 case ARDSettingsSectionVideoResolution: 150 return [self videoResolutionTableViewCellForTableView:tableView 151 atIndexPath:indexPath]; 152 153 case ARDSettingsSectionVideoCodec: 154 return [self videoCodecTableViewCellForTableView:tableView 155 atIndexPath:indexPath]; 156 157 case ARDSettingsSectionBitRate: 158 return [self bitrateTableViewCellForTableView:tableView 159 atIndexPath:indexPath]; 160 161 default: 162 return [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 163 reuseIdentifier:@"identifier"]; 164 } 165 } 166 167 - (void)tableView:(UITableView *)tableView 168 didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 169 switch (indexPath.section) { 170 case ARDSettingsSectionVideoResolution: 171 [self tableView:tableView disSelectVideoResolutionAtIndex:indexPath]; 172 break; 173 174 case ARDSettingsSectionVideoCodec: 175 [self tableView:tableView didSelectVideoCodecCellAtIndexPath:indexPath]; 176 break; 177 } 178 } 179 180 #pragma mark - Table view delegate(Video Resolution) 181 182 - (UITableViewCell *) 183 videoResolutionTableViewCellForTableView:(UITableView *)tableView 184 atIndexPath:(NSIndexPath *)indexPath { 185 NSString *dequeueIdentifier = @"ARDSettingsVideoResolutionViewCellIdentifier"; 186 UITableViewCell *cell = 187 [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier]; 188 if (!cell) { 189 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 190 reuseIdentifier:dequeueIdentifier]; 191 } 192 NSString *resolution = self.videoResolutionArray[indexPath.row]; 193 cell.textLabel.text = resolution; 194 if ([resolution 195 isEqualToString:[_settingsModel 196 currentVideoResolutionSettingFromStore]]) { 197 cell.accessoryType = UITableViewCellAccessoryCheckmark; 198 } else { 199 cell.accessoryType = UITableViewCellAccessoryNone; 200 } 201 202 return cell; 203 } 204 205 - (void)tableView:(UITableView *)tableView 206 disSelectVideoResolutionAtIndex:(NSIndexPath *)indexPath { 207 [self tableView:tableView 208 updateListSelectionAtIndexPath:indexPath 209 inSection:ARDSettingsSectionVideoResolution]; 210 211 NSString *videoResolution = self.videoResolutionArray[indexPath.row]; 212 [_settingsModel storeVideoResolutionSetting:videoResolution]; 213 } 214 215 #pragma mark - Table view delegate(Video Codec) 216 217 - (UITableViewCell *) 218 videoCodecTableViewCellForTableView:(UITableView *)tableView 219 atIndexPath:(NSIndexPath *)indexPath { 220 NSString *dequeueIdentifier = @"ARDSettingsVideoCodecCellIdentifier"; 221 UITableViewCell *cell = 222 [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier]; 223 if (!cell) { 224 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 225 reuseIdentifier:dequeueIdentifier]; 226 } 227 RTC_OBJC_TYPE(RTCVideoCodecInfo) *codec = self.videoCodecArray[indexPath.row]; 228 cell.textLabel.text = [codec humanReadableDescription]; 229 if ([codec isEqualToCodecInfo:[_settingsModel 230 currentVideoCodecSettingFromStore]]) { 231 cell.accessoryType = UITableViewCellAccessoryCheckmark; 232 } else { 233 cell.accessoryType = UITableViewCellAccessoryNone; 234 } 235 236 return cell; 237 } 238 239 - (void)tableView:(UITableView *)tableView 240 didSelectVideoCodecCellAtIndexPath:(NSIndexPath *)indexPath { 241 [self tableView:tableView 242 updateListSelectionAtIndexPath:indexPath 243 inSection:ARDSettingsSectionVideoCodec]; 244 245 RTC_OBJC_TYPE(RTCVideoCodecInfo) *videoCodec = 246 self.videoCodecArray[indexPath.row]; 247 [_settingsModel storeVideoCodecSetting:videoCodec]; 248 } 249 250 #pragma mark - Table view delegate(Bitrate) 251 252 - (UITableViewCell *)bitrateTableViewCellForTableView:(UITableView *)tableView 253 atIndexPath:(NSIndexPath *)indexPath { 254 NSString *dequeueIdentifier = @"ARDSettingsBitrateCellIdentifier"; 255 UITableViewCell *cell = 256 [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier]; 257 if (!cell) { 258 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 259 reuseIdentifier:dequeueIdentifier]; 260 261 UITextField *textField = [[UITextField alloc] 262 initWithFrame:CGRectMake(10, 263 0, 264 cell.bounds.size.width - 20, 265 cell.bounds.size.height)]; 266 NSString *currentMaxBitrate = 267 [_settingsModel currentMaxBitrateSettingFromStore].stringValue; 268 textField.text = currentMaxBitrate; 269 textField.placeholder = @"Enter max bit rate (kbps)"; 270 textField.keyboardType = UIKeyboardTypeNumberPad; 271 textField.delegate = self; 272 273 // Numerical keyboards have no return button, we need to add one manually. 274 UIToolbar *numberToolbar = [[UIToolbar alloc] 275 initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)]; 276 numberToolbar.items = @[ 277 [[UIBarButtonItem alloc] 278 initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace 279 target:nil 280 action:nil], 281 [[UIBarButtonItem alloc] 282 initWithTitle:@"Apply" 283 style:UIBarButtonItemStyleDone 284 target:self 285 action:@selector(numberTextFieldDidEndEditing:)] 286 ]; 287 [numberToolbar sizeToFit]; 288 289 textField.inputAccessoryView = numberToolbar; 290 [cell addSubview:textField]; 291 } 292 return cell; 293 } 294 295 - (void)numberTextFieldDidEndEditing:(id)sender { 296 [self.view endEditing:YES]; 297 } 298 299 - (void)textFieldDidEndEditing:(UITextField *)textField { 300 NSNumber *bitrateNumber = nil; 301 302 if (textField.text.length != 0) { 303 bitrateNumber = [NSNumber numberWithInteger:textField.text.intValue]; 304 } 305 306 [_settingsModel storeMaxBitrateSetting:bitrateNumber]; 307 } 308 309 #pragma mark - Table view delegate(Audio settings) 310 311 - (UITableViewCell *) 312 audioSettingsTableViewCellForTableView:(UITableView *)tableView 313 atIndexPath:(NSIndexPath *)indexPath { 314 NSString *dequeueIdentifier = @"ARDSettingsAudioSettingsCellIdentifier"; 315 UITableViewCell *cell = 316 [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier]; 317 if (!cell) { 318 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 319 reuseIdentifier:dequeueIdentifier]; 320 cell.selectionStyle = UITableViewCellSelectionStyleNone; 321 UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectZero]; 322 switchView.tag = indexPath.row; 323 [switchView addTarget:self 324 action:@selector(audioSettingSwitchChanged:) 325 forControlEvents:UIControlEventValueChanged]; 326 cell.accessoryView = switchView; 327 } 328 329 cell.textLabel.text = [self labelForAudioSettingAtIndexPathRow:indexPath.row]; 330 UISwitch *switchView = (UISwitch *)cell.accessoryView; 331 switchView.on = [self valueForAudioSettingAtIndexPathRow:indexPath.row]; 332 333 return cell; 334 } 335 336 - (NSString *)labelForAudioSettingAtIndexPathRow:(NSInteger)setting { 337 switch (setting) { 338 case ARDAudioSettingsAudioOnly: 339 return @"Audio only"; 340 case ARDAudioSettingsCreateAecDump: 341 return @"Create AecDump"; 342 case ARDAudioSettingsUseManualAudioConfig: 343 return @"Use manual audio config"; 344 default: 345 return @""; 346 } 347 } 348 349 - (BOOL)valueForAudioSettingAtIndexPathRow:(NSInteger)setting { 350 switch (setting) { 351 case ARDAudioSettingsAudioOnly: 352 return [_settingsModel currentAudioOnlySettingFromStore]; 353 case ARDAudioSettingsCreateAecDump: 354 return [_settingsModel currentCreateAecDumpSettingFromStore]; 355 case ARDAudioSettingsUseManualAudioConfig: 356 return [_settingsModel currentUseManualAudioConfigSettingFromStore]; 357 default: 358 return NO; 359 } 360 } 361 362 - (void)audioSettingSwitchChanged:(UISwitch *)sender { 363 switch (sender.tag) { 364 case ARDAudioSettingsAudioOnly: { 365 [_settingsModel storeAudioOnlySetting:sender.isOn]; 366 break; 367 } 368 case ARDAudioSettingsCreateAecDump: { 369 [_settingsModel storeCreateAecDumpSetting:sender.isOn]; 370 break; 371 } 372 case ARDAudioSettingsUseManualAudioConfig: { 373 [_settingsModel storeUseManualAudioConfigSetting:sender.isOn]; 374 break; 375 } 376 default: 377 break; 378 } 379 } 380 381 @end 382 NS_ASSUME_NONNULL_END