denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 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" |
denicija | 2256e04 | 2016-11-09 06:26:18 -0800 | [diff] [blame^] | 12 | #import "ARDSettingsModel.h" |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 13 | |
| 14 | NS_ASSUME_NONNULL_BEGIN |
denicija | b04b5c2 | 2016-11-09 04:28:46 -0800 | [diff] [blame] | 15 | |
| 16 | typedef NS_ENUM(int, ARDSettingsSections) { |
| 17 | ARDSettingsSectionMediaConstraints = 0, |
| 18 | ARDSettingsSectionBitRate |
| 19 | }; |
| 20 | |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 21 | @interface ARDSettingsViewController () { |
denicija | 2256e04 | 2016-11-09 06:26:18 -0800 | [diff] [blame^] | 22 | ARDSettingsModel *_settingsModel; |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 23 | } |
| 24 | |
| 25 | @end |
| 26 | |
| 27 | @implementation ARDSettingsViewController |
| 28 | |
| 29 | - (instancetype)initWithStyle:(UITableViewStyle)style |
denicija | 2256e04 | 2016-11-09 06:26:18 -0800 | [diff] [blame^] | 30 | settingsModel:(ARDSettingsModel *)settingsModel { |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 31 | self = [super initWithStyle:style]; |
| 32 | if (self) { |
denicija | 2256e04 | 2016-11-09 06:26:18 -0800 | [diff] [blame^] | 33 | _settingsModel = settingsModel; |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 34 | } |
| 35 | return self; |
| 36 | } |
| 37 | |
| 38 | #pragma mark - View lifecycle |
| 39 | |
| 40 | - (void)viewDidLoad { |
| 41 | [super viewDidLoad]; |
| 42 | self.title = @"Settings"; |
| 43 | [self addDoneBarButton]; |
| 44 | } |
| 45 | |
| 46 | - (void)viewDidAppear:(BOOL)animated { |
| 47 | [super viewDidAppear:animated]; |
| 48 | [self selectCurrentlyStoredOrDefaultMediaConstraints]; |
| 49 | } |
| 50 | |
| 51 | #pragma mark - Data source |
| 52 | |
| 53 | - (NSArray<NSString *> *)mediaConstraintsArray { |
denicija | 2256e04 | 2016-11-09 06:26:18 -0800 | [diff] [blame^] | 54 | return _settingsModel.availableVideoResoultionsMediaConstraints; |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | #pragma mark - |
| 58 | |
| 59 | - (void)addDoneBarButton { |
| 60 | UIBarButtonItem *barItem = |
| 61 | [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone |
| 62 | target:self |
| 63 | action:@selector(dismissModally:)]; |
| 64 | self.navigationItem.leftBarButtonItem = barItem; |
| 65 | } |
| 66 | |
| 67 | - (void)selectCurrentlyStoredOrDefaultMediaConstraints { |
denicija | 2256e04 | 2016-11-09 06:26:18 -0800 | [diff] [blame^] | 68 | NSString *currentSelection = [_settingsModel currentVideoResoultionConstraintFromStore]; |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 69 | |
| 70 | NSUInteger indexOfSelection = [[self mediaConstraintsArray] indexOfObject:currentSelection]; |
| 71 | NSIndexPath *pathToBeSelected = [NSIndexPath indexPathForRow:indexOfSelection inSection:0]; |
| 72 | [self.tableView selectRowAtIndexPath:pathToBeSelected |
| 73 | animated:NO |
| 74 | scrollPosition:UITableViewScrollPositionNone]; |
| 75 | // Manully invoke the delegate method because the previous invocation will not. |
| 76 | [self tableView:self.tableView didSelectRowAtIndexPath:pathToBeSelected]; |
| 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 { |
denicija | b04b5c2 | 2016-11-09 04:28:46 -0800 | [diff] [blame] | 88 | return 2; |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 89 | } |
| 90 | |
denicija | 40532a1 | 2016-11-08 04:00:53 -0800 | [diff] [blame] | 91 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { |
denicija | b04b5c2 | 2016-11-09 04:28:46 -0800 | [diff] [blame] | 92 | if ([self sectionIsMediaConstraints:section]) { |
| 93 | return self.mediaConstraintsArray.count; |
| 94 | } |
| 95 | |
| 96 | return 1; |
denicija | 3babb99 | 2016-11-07 07:23:56 -0800 | [diff] [blame] | 97 | } |
| 98 | |
denicija | b04b5c2 | 2016-11-09 04:28:46 -0800 | [diff] [blame] | 99 | #pragma mark - Index path helpers |
denicija | 40532a1 | 2016-11-08 04:00:53 -0800 | [diff] [blame] | 100 | |
| 101 | - (BOOL)sectionIsMediaConstraints:(int)section { |
denicija | b04b5c2 | 2016-11-09 04:28:46 -0800 | [diff] [blame] | 102 | return section == ARDSettingsSectionMediaConstraints; |
| 103 | } |
| 104 | |
| 105 | - (BOOL)sectionIsBitrate:(int)section { |
| 106 | return section == ARDSettingsSectionBitRate; |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 107 | } |
| 108 | |
| 109 | - (BOOL)indexPathIsMediaConstraints:(NSIndexPath *)indexPath { |
| 110 | return [self sectionIsMediaConstraints:indexPath.section]; |
| 111 | } |
| 112 | |
denicija | b04b5c2 | 2016-11-09 04:28:46 -0800 | [diff] [blame] | 113 | - (BOOL)indexPathIsBitrate:(NSIndexPath *)indexPath { |
| 114 | return [self sectionIsBitrate:indexPath.section]; |
| 115 | } |
| 116 | |
| 117 | #pragma mark - Table view delegate |
| 118 | |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 119 | - (nullable NSString *)tableView:(UITableView *)tableView |
| 120 | titleForHeaderInSection:(NSInteger)section { |
| 121 | if ([self sectionIsMediaConstraints:section]) { |
| 122 | return @"Media constraints"; |
| 123 | } |
denicija | b04b5c2 | 2016-11-09 04:28:46 -0800 | [diff] [blame] | 124 | |
| 125 | if ([self sectionIsBitrate:section]) { |
| 126 | return @"Maximum bitrate"; |
| 127 | } |
| 128 | |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 129 | return @""; |
| 130 | } |
| 131 | |
| 132 | - (UITableViewCell *)tableView:(UITableView *)tableView |
| 133 | cellForRowAtIndexPath:(NSIndexPath *)indexPath { |
| 134 | if ([self indexPathIsMediaConstraints:indexPath]) { |
| 135 | return [self mediaConstraintsTableViewCellForTableView:tableView atIndexPath:indexPath]; |
| 136 | } |
denicija | b04b5c2 | 2016-11-09 04:28:46 -0800 | [diff] [blame] | 137 | |
| 138 | if ([self indexPathIsBitrate:indexPath]) { |
| 139 | return [self bitrateTableViewCellForTableView:tableView atIndexPath:indexPath]; |
| 140 | } |
| 141 | |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 142 | return [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault |
| 143 | reuseIdentifier:@"identifier"]; |
| 144 | } |
| 145 | |
| 146 | - (nullable NSIndexPath *)tableView:(UITableView *)tableView |
| 147 | willSelectRowAtIndexPath:(nonnull NSIndexPath *)indexPath { |
| 148 | if ([self indexPathIsMediaConstraints:indexPath]) { |
| 149 | return [self tableView:tableView willDeselectMediaConstraintsRowAtIndexPath:indexPath]; |
| 150 | } |
| 151 | return indexPath; |
| 152 | } |
| 153 | |
| 154 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { |
| 155 | if ([self indexPathIsMediaConstraints:indexPath]) { |
| 156 | [self tableView:tableView didSelectMediaConstraintsCellAtIndexPath:indexPath]; |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | #pragma mark - Table view delegate(Media Constraints) |
| 161 | |
| 162 | - (UITableViewCell *)mediaConstraintsTableViewCellForTableView:(UITableView *)tableView |
| 163 | atIndexPath:(NSIndexPath *)indexPath { |
| 164 | NSString *dequeueIdentifier = @"ARDSettingsMediaConstraintsViewCellIdentifier"; |
| 165 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier]; |
| 166 | if (!cell) { |
| 167 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault |
| 168 | reuseIdentifier:dequeueIdentifier]; |
| 169 | } |
| 170 | cell.textLabel.text = self.mediaConstraintsArray[indexPath.row]; |
| 171 | return cell; |
| 172 | } |
| 173 | |
| 174 | - (void)tableView:(UITableView *)tableView |
| 175 | didSelectMediaConstraintsCellAtIndexPath:(NSIndexPath *)indexPath { |
| 176 | UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; |
| 177 | cell.accessoryType = UITableViewCellAccessoryCheckmark; |
| 178 | |
| 179 | NSString *mediaConstraintsString = self.mediaConstraintsArray[indexPath.row]; |
denicija | 2256e04 | 2016-11-09 06:26:18 -0800 | [diff] [blame^] | 180 | [_settingsModel storeVideoResoultionConstraint:mediaConstraintsString]; |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 181 | } |
| 182 | |
| 183 | - (NSIndexPath *)tableView:(UITableView *)tableView |
| 184 | willDeselectMediaConstraintsRowAtIndexPath:(NSIndexPath *)indexPath { |
| 185 | NSIndexPath *oldSelection = [tableView indexPathForSelectedRow]; |
| 186 | UITableViewCell *cell = [tableView cellForRowAtIndexPath:oldSelection]; |
| 187 | cell.accessoryType = UITableViewCellAccessoryNone; |
| 188 | return indexPath; |
| 189 | } |
| 190 | |
denicija | b04b5c2 | 2016-11-09 04:28:46 -0800 | [diff] [blame] | 191 | #pragma mark - Table view delegate(Bitrate) |
| 192 | |
| 193 | - (UITableViewCell *)bitrateTableViewCellForTableView:(UITableView *)tableView |
| 194 | atIndexPath:(NSIndexPath *)indexPath { |
| 195 | NSString *dequeueIdentifier = @"ARDSettingsBitrateCellIdentifier"; |
| 196 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier]; |
| 197 | if (!cell) { |
| 198 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault |
| 199 | reuseIdentifier:dequeueIdentifier]; |
| 200 | |
| 201 | UITextField *textField = [[UITextField alloc] |
| 202 | initWithFrame:CGRectMake(10, 0, cell.bounds.size.width - 20, cell.bounds.size.height)]; |
| 203 | textField.placeholder = @"Enter max bit rate (kbps)"; |
| 204 | textField.keyboardType = UIKeyboardTypeNumberPad; |
| 205 | |
| 206 | // Numerical keyboards have no return button, we need to add one manually. |
| 207 | UIToolbar *numberToolbar = |
| 208 | [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)]; |
| 209 | numberToolbar.items = @[ |
| 210 | [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace |
| 211 | target:nil |
| 212 | action:nil], |
| 213 | [[UIBarButtonItem alloc] initWithTitle:@"Apply" |
| 214 | style:UIBarButtonItemStyleDone |
| 215 | target:self |
| 216 | action:@selector(numberTextFieldDidEndEditing:)] |
| 217 | ]; |
| 218 | [numberToolbar sizeToFit]; |
| 219 | |
| 220 | textField.inputAccessoryView = numberToolbar; |
| 221 | [cell addSubview:textField]; |
| 222 | } |
| 223 | return cell; |
| 224 | } |
| 225 | |
| 226 | - (void)numberTextFieldDidEndEditing:(id)sender { |
| 227 | [self.view endEditing:YES]; |
| 228 | } |
| 229 | |
denicija | d17d536 | 2016-11-02 02:56:09 -0700 | [diff] [blame] | 230 | @end |
| 231 | NS_ASSUME_NONNULL_END |