Alexandre Lision | 8af73cb | 2013-12-10 14:11:20 -0500 | [diff] [blame] | 1 | /* $Id$ */ |
| 2 | /* |
| 3 | * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com) |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation; either version 2 of the License, or |
| 8 | * (at your option) any later version. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software |
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 18 | */ |
| 19 | #import "RootViewController.h" |
| 20 | #import "gui.h" |
| 21 | #import "systest.h" |
| 22 | |
| 23 | /* Sleep interval duration, change to shorter duration for better |
| 24 | * interaction but make sure there is enough time for the other |
| 25 | * thread to do what it's supposed to do |
| 26 | */ |
| 27 | #define SLEEP_INTERVAL 0.5 |
| 28 | |
| 29 | @implementation RootViewController |
| 30 | @synthesize titles; |
| 31 | @synthesize menus; |
| 32 | @synthesize testView; |
| 33 | |
| 34 | RootViewController *view; |
| 35 | |
| 36 | bool systest_initialized; |
| 37 | bool thread_quit; |
| 38 | gui_menu *gmenu; |
| 39 | int section; |
| 40 | int row; |
| 41 | const char *ctitle; |
| 42 | const char *cmsg; |
| 43 | enum gui_flag cflag; |
| 44 | |
| 45 | pj_status_t gui_init(gui_menu *menu) |
| 46 | { |
| 47 | PJ_UNUSED_ARG(menu); |
| 48 | return PJ_SUCCESS; |
| 49 | } |
| 50 | |
| 51 | /* Run GUI main loop */ |
| 52 | pj_status_t gui_start(gui_menu *menu) |
| 53 | { |
| 54 | view.titles = [NSMutableArray arrayWithCapacity:menu->submenu_cnt]; |
| 55 | view.menus = [NSMutableArray arrayWithCapacity:menu->submenu_cnt]; |
| 56 | NSMutableArray *smenu; |
| 57 | for (int i = 0; i < menu->submenu_cnt; i++) { |
| 58 | NSString *str = [NSString stringWithFormat:@"%s" , menu->submenus[i]->title]; |
| 59 | [view.titles addObject: str]; |
| 60 | smenu = [NSMutableArray arrayWithCapacity:menu->submenus[i]->submenu_cnt]; |
| 61 | /* We do not need the last two menus of the "Tests" menu (NULL and "Exit"), |
| 62 | * so subtract by 2 |
| 63 | */ |
| 64 | for (int j = 0; j < menu->submenus[i]->submenu_cnt - (i==0? 2: 0); j++) { |
| 65 | str = [NSString stringWithFormat:@"%s" , menu->submenus[i]->submenus[j]->title]; |
| 66 | [smenu addObject:str]; |
| 67 | } |
| 68 | [view.menus addObject:smenu]; |
| 69 | } |
| 70 | gmenu = menu; |
| 71 | |
| 72 | return PJ_SUCCESS; |
| 73 | } |
| 74 | |
| 75 | /* Signal GUI mainloop to stop */ |
| 76 | void gui_destroy(void) |
| 77 | { |
| 78 | } |
| 79 | |
| 80 | /* AUX: display messagebox */ |
| 81 | enum gui_key gui_msgbox(const char *title, const char *message, enum gui_flag flag) |
| 82 | { |
| 83 | ctitle = title; |
| 84 | cmsg = message; |
| 85 | cflag = flag; |
| 86 | [view performSelectorOnMainThread:@selector(showMsg) withObject:nil waitUntilDone:YES]; |
| 87 | |
| 88 | view.testView.key = 0; |
| 89 | while(view.testView.key == 0) { |
| 90 | /* Let the main thread do its job (refresh the view) while we wait for |
| 91 | * user interaction (button click) |
| 92 | */ |
| 93 | [NSThread sleepForTimeInterval:SLEEP_INTERVAL]; |
| 94 | } |
| 95 | |
| 96 | if (view.testView.key == 1) |
| 97 | return KEY_OK; |
| 98 | else |
| 99 | return (flag == WITH_YESNO? KEY_NO: KEY_CANCEL); |
| 100 | } |
| 101 | |
| 102 | /* AUX: sleep */ |
| 103 | void gui_sleep(unsigned sec) |
| 104 | { |
| 105 | [NSThread sleepForTimeInterval:sec]; |
| 106 | } |
| 107 | |
| 108 | - (void)viewDidLoad { |
| 109 | [super viewDidLoad]; |
| 110 | |
| 111 | view = self; |
| 112 | |
| 113 | /* Get a writable path for output files */ |
| 114 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); |
| 115 | NSString *documentsDirectory = [paths objectAtIndex:0]; |
| 116 | [documentsDirectory getCString:doc_path maxLength:PATH_LENGTH encoding:NSASCIIStringEncoding]; |
| 117 | strncat(doc_path, "/", PATH_LENGTH); |
| 118 | |
| 119 | /* Get path for our test resources (the wav files) */ |
| 120 | NSString *resPath = [[NSBundle mainBundle] resourcePath]; |
| 121 | [resPath getCString:res_path maxLength:PATH_LENGTH encoding:NSASCIIStringEncoding]; |
| 122 | strncat(res_path, "/", PATH_LENGTH); |
| 123 | |
| 124 | systest_initialized = false; |
| 125 | thread_quit = false; |
| 126 | [NSThread detachNewThreadSelector:@selector(startTest) toTarget:self withObject:nil]; |
| 127 | /* Let our new thread initialize */ |
| 128 | while (!systest_initialized) { |
| 129 | [NSThread sleepForTimeInterval:SLEEP_INTERVAL]; |
| 130 | } |
| 131 | |
| 132 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. |
| 133 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; |
| 134 | } |
| 135 | |
| 136 | /* |
| 137 | - (void)viewWillAppear:(BOOL)animated { |
| 138 | [super viewWillAppear:animated]; |
| 139 | } |
| 140 | */ |
| 141 | /* |
| 142 | - (void)viewDidAppear:(BOOL)animated { |
| 143 | [super viewDidAppear:animated]; |
| 144 | } |
| 145 | */ |
| 146 | /* |
| 147 | - (void)viewWillDisappear:(BOOL)animated { |
| 148 | [super viewWillDisappear:animated]; |
| 149 | } |
| 150 | */ |
| 151 | /* |
| 152 | - (void)viewDidDisappear:(BOOL)animated { |
| 153 | [super viewDidDisappear:animated]; |
| 154 | } |
| 155 | */ |
| 156 | |
| 157 | /* |
| 158 | // Override to allow orientations other than the default portrait orientation. |
| 159 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { |
| 160 | // Return YES for supported orientations. |
| 161 | return (interfaceOrientation == UIInterfaceOrientationPortrait); |
| 162 | } |
| 163 | */ |
| 164 | |
| 165 | - (void)didReceiveMemoryWarning { |
| 166 | // Releases the view if it doesn't have a superview. |
| 167 | [super didReceiveMemoryWarning]; |
| 168 | |
| 169 | // Release any cached data, images, etc that aren't in use. |
| 170 | } |
| 171 | |
| 172 | - (void)viewDidUnload { |
| 173 | // Release anything that can be recreated in viewDidLoad or on demand. |
| 174 | // e.g. self.myOutlet = nil; |
| 175 | self.titles = nil; |
| 176 | self.menus = nil; |
| 177 | |
| 178 | thread_quit = true; |
| 179 | [NSThread sleepForTimeInterval:SLEEP_INTERVAL]; |
| 180 | } |
| 181 | |
| 182 | |
| 183 | #pragma mark Table view methods |
| 184 | |
| 185 | |
| 186 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { |
| 187 | return [titles count]; |
| 188 | } |
| 189 | |
| 190 | |
| 191 | // Customize the number of rows in the table view. |
| 192 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { |
| 193 | return [[menus objectAtIndex:section] count]; |
| 194 | } |
| 195 | |
| 196 | |
| 197 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { |
| 198 | // The header for the section is the region name -- get this from the region at the section index. |
| 199 | return [titles objectAtIndex:section]; |
| 200 | } |
| 201 | |
| 202 | // Customize the appearance of table view cells. |
| 203 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { |
| 204 | |
| 205 | static NSString *CellIdentifier = @"Cell"; |
| 206 | |
| 207 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
| 208 | if (cell == nil) { |
| 209 | cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; |
| 210 | } |
| 211 | |
| 212 | // Configure the cell. |
| 213 | cell.textLabel.text = [[menus objectAtIndex:indexPath.section] objectAtIndex:indexPath.row]; |
| 214 | |
| 215 | return cell; |
| 216 | } |
| 217 | |
| 218 | - (void)startTest { |
| 219 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
| 220 | if (systest_init() != PJ_SUCCESS) { |
| 221 | [pool release]; |
| 222 | return; |
| 223 | } |
| 224 | |
| 225 | systest_run(); |
| 226 | |
| 227 | systest_initialized = 1; |
| 228 | while(!thread_quit) { |
| 229 | section = -1; |
| 230 | while (section == -1) { |
| 231 | [NSThread sleepForTimeInterval:SLEEP_INTERVAL]; |
| 232 | } |
| 233 | (*gmenu->submenus[section]->submenus[row]->handler)(); |
| 234 | cmsg = NULL; |
| 235 | [view performSelectorOnMainThread:@selector(showMsg) withObject:nil waitUntilDone:YES]; |
| 236 | } |
| 237 | |
| 238 | systest_deinit(); |
| 239 | [pool release]; |
| 240 | } |
| 241 | |
| 242 | - (void)showMsg { |
| 243 | if (cmsg == NULL) { |
| 244 | self.testView.testDesc.text = [self.testView.testDesc.text stringByAppendingString: @"Finished"]; |
| 245 | [self.testView.testDesc scrollRangeToVisible:NSMakeRange([self.testView.testDesc.text length] - 1, 1)]; |
| 246 | [self.testView.button1 setHidden:true]; |
| 247 | [self.testView.button2 setHidden:true]; |
| 248 | return; |
| 249 | } |
| 250 | self.testView.title = [NSString stringWithFormat:@"%s", ctitle]; |
| 251 | self.testView.testDesc.text = [self.testView.testDesc.text stringByAppendingString: [NSString stringWithFormat:@"%s\n\n", cmsg]]; |
| 252 | [self.testView.testDesc scrollRangeToVisible:NSMakeRange([self.testView.testDesc.text length] - 1, 1)]; |
| 253 | |
| 254 | [self.testView.button1 setHidden:false]; |
| 255 | [self.testView.button2 setHidden:false]; |
| 256 | if (cflag == WITH_YESNO) { |
| 257 | [self.testView.button1 setTitle:@"Yes" forState:UIControlStateNormal]; |
| 258 | [self.testView.button2 setTitle:@"No" forState:UIControlStateNormal]; |
| 259 | } else if (cflag == WITH_OK) { |
| 260 | [self.testView.button1 setTitle:@"OK" forState:UIControlStateNormal]; |
| 261 | [self.testView.button2 setHidden:true]; |
| 262 | } else if (cflag == WITH_OKCANCEL) { |
| 263 | [self.testView.button1 setTitle:@"OK" forState:UIControlStateNormal]; |
| 264 | [self.testView.button2 setTitle:@"Cancel" forState:UIControlStateNormal]; |
| 265 | } |
| 266 | } |
| 267 | |
| 268 | |
| 269 | // Override to support row selection in the table view. |
| 270 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { |
| 271 | |
| 272 | // Navigation logic may go here -- for example, create and push another view controller. |
| 273 | // AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil]; |
| 274 | // [self.navigationController pushViewController:anotherViewController animated:YES]; |
| 275 | // [anotherViewController release]; |
| 276 | |
| 277 | if (self.testView == nil) { |
| 278 | self.testView = [[TestViewController alloc] initWithNibName:@"TestViewController" bundle:[NSBundle mainBundle]]; |
| 279 | } |
| 280 | |
| 281 | [self.navigationController pushViewController:self.testView animated:YES]; |
| 282 | self.testView.title = [[menus objectAtIndex:indexPath.section] objectAtIndex:indexPath.row]; |
| 283 | self.testView.testDesc.text = @""; |
| 284 | section = indexPath.section; |
| 285 | row = indexPath.row; |
| 286 | } |
| 287 | |
| 288 | |
| 289 | /* |
| 290 | // Override to support conditional editing of the table view. |
| 291 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { |
| 292 | // Return NO if you do not want the specified item to be editable. |
| 293 | return YES; |
| 294 | } |
| 295 | */ |
| 296 | |
| 297 | |
| 298 | /* |
| 299 | // Override to support editing the table view. |
| 300 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { |
| 301 | |
| 302 | if (editingStyle == UITableViewCellEditingStyleDelete) { |
| 303 | // Delete the row from the data source. |
| 304 | [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; |
| 305 | } |
| 306 | else if (editingStyle == UITableViewCellEditingStyleInsert) { |
| 307 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view. |
| 308 | } |
| 309 | } |
| 310 | */ |
| 311 | |
| 312 | |
| 313 | /* |
| 314 | // Override to support rearranging the table view. |
| 315 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { |
| 316 | } |
| 317 | */ |
| 318 | |
| 319 | |
| 320 | /* |
| 321 | // Override to support conditional rearranging of the table view. |
| 322 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { |
| 323 | // Return NO if you do not want the item to be re-orderable. |
| 324 | return YES; |
| 325 | } |
| 326 | */ |
| 327 | |
| 328 | |
| 329 | - (void)dealloc { |
| 330 | [super dealloc]; |
| 331 | } |
| 332 | |
| 333 | |
| 334 | @end |
| 335 | |