diff --git a/ios/RetroArch.xcodeproj/project.pbxproj b/ios/RetroArch.xcodeproj/project.pbxproj index 692bf771cd..3ae59b4e56 100644 --- a/ios/RetroArch.xcodeproj/project.pbxproj +++ b/ios/RetroArch.xcodeproj/project.pbxproj @@ -80,6 +80,7 @@ 96AFAFAC16C1E279009DE44C /* state_tracker.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF7B16C1E00A009DE44C /* state_tracker.c */; }; 96AFAFAD16C1EEE9009DE44C /* sinc.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEF716C1DC73009DE44C /* sinc.c */; }; 96AFAFD416C1FBC0009DE44C /* input_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAFC916C1FBC0009DE44C /* input_common.c */; }; + 96C19C2216D2F3BA00FE8D5A /* RADirectoryFilterList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96C19C2116D2F3BA00FE8D5A /* RADirectoryFilterList.m */; }; 96CF015016C2C0B700ABF9C9 /* overlay.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAFCE16C1FBC0009DE44C /* overlay.c */; }; 96CF015C16C2F72900ABF9C9 /* ios_input.c in Sources */ = {isa = PBXBuildFile; fileRef = 96CF015B16C2F72900ABF9C9 /* ios_input.c */; }; /* End PBXBuildFile section */ @@ -223,6 +224,7 @@ 96AFAFCA16C1FBC0009DE44C /* input_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input_common.h; sourceTree = ""; }; 96AFAFCE16C1FBC0009DE44C /* overlay.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = overlay.c; sourceTree = ""; }; 96AFAFCF16C1FBC0009DE44C /* overlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = overlay.h; sourceTree = ""; }; + 96C19C2116D2F3BA00FE8D5A /* RADirectoryFilterList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RADirectoryFilterList.m; sourceTree = ""; }; 96CF015B16C2F72900ABF9C9 /* ios_input.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ios_input.c; sourceTree = ""; }; /* End PBXFileReference section */ @@ -301,6 +303,7 @@ 96366C6F16CAF62200D64A22 /* settings */, 96AFAE3416C1D4EA009DE44C /* Supporting Files */, 96CF015B16C2F72900ABF9C9 /* ios_input.c */, + 96C19C2116D2F3BA00FE8D5A /* RADirectoryFilterList.m */, 963F5AC416CC523B009BBD19 /* RADirectoryList.m */, 963F5AC516CC523B009BBD19 /* RAGameView.m */, 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */, @@ -667,6 +670,7 @@ 963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */, 963F5AC916CC523B009BBD19 /* RAModuleList.m in Sources */, 96096DD816D1ABAF00BF4499 /* RAModuleInfoList.m in Sources */, + 96C19C2216D2F3BA00FE8D5A /* RADirectoryFilterList.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/RetroArch/RADirectoryFilterList.m b/ios/RetroArch/RADirectoryFilterList.m new file mode 100644 index 0000000000..0e9bf15f27 --- /dev/null +++ b/ios/RetroArch/RADirectoryFilterList.m @@ -0,0 +1,80 @@ +// +// dirlist.m +// RetroArch +// +// Created by Jason Fetters on 2/7/13. +// Copyright (c) 2013 RetroArch. All rights reserved. +// + +@implementation RADirectoryFilterList +{ + NSString* _path; + + config_file_t* _filterList; + unsigned _filterCount; +} + +- (id)initWithPath:(NSString*)path +{ + self = [super initWithStyle:UITableViewStylePlain]; + + _path = path; + _filterList = config_file_new([[path stringByAppendingPathComponent:@".rafilter"] UTF8String]); + + if (!_filterList || !config_get_uint(_filterList, "filter_count", &_filterCount) || _filterCount == 0) + { + [RetroArch_iOS displayErrorMessage:@"No valid filters were found."]; + } + + [self setTitle: [path lastPathComponent]]; + + return self; +} + +- (void)dealloc +{ + if (_filterList) + config_file_free(_filterList); +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (_filterList) + { + NSString* regexKey = [NSString stringWithFormat:@"filter_%d_regex", indexPath.row + 1]; + + char* regex = 0; + if (config_get_string(_filterList, [regexKey UTF8String], ®ex)) + { + NSRegularExpression* expr = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithUTF8String:regex] options:0 error:nil]; + free(regex); + + [[RetroArch_iOS get] pushViewController:[[RADirectoryList alloc] initWithPath:_path filter:expr]]; + } + } +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + return _filterCount; +} + +- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSString* nameKey = [NSString stringWithFormat:@"filter_%d_name", indexPath.row + 1]; + + char* nameString = 0; + if (_filterList && config_get_string(_filterList, [nameKey UTF8String], &nameString)) + { + nameKey = [NSString stringWithUTF8String:nameString]; + free(nameString); + } + + UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"filter"]; + cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"filter"]; + cell.textLabel.text = nameKey; + + return cell; +} + +@end diff --git a/ios/RetroArch/RADirectoryList.m b/ios/RetroArch/RADirectoryList.m index 6f59db41a5..dc4751d7fb 100644 --- a/ios/RetroArch/RADirectoryList.m +++ b/ios/RetroArch/RADirectoryList.m @@ -6,6 +6,11 @@ // Copyright (c) 2013 RetroArch. All rights reserved. // +static BOOL is_file(NSString* path) +{ + return [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:nil]; +} + static BOOL is_directory(NSString* path) { BOOL result = NO; @@ -19,7 +24,22 @@ static BOOL is_directory(NSString* path) NSArray* _list; } -- (id)initWithPath:(NSString*)path ++ (id)directoryListWithPath:(NSString*)path +{ + if (path && !is_directory(path)) + { + [RetroArch_iOS displayErrorMessage:@"Browsed path is not a directory."]; + path = nil; + } + + if (path && is_file([path stringByAppendingPathComponent:@".rafilter"])) + return [[RADirectoryFilterList alloc] initWithPath:path]; + else + return [[RADirectoryList alloc] initWithPath:path filter:nil]; + +} + +- (id)initWithPath:(NSString*)path filter:(NSRegularExpression*)regex { self = [super initWithStyle:UITableViewStylePlain]; @@ -35,6 +55,17 @@ static BOOL is_directory(NSString* path) _list = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:_path error:nil]; _list = [_path stringsByAppendingPaths:_list]; + if (regex) + { + _list = [_list filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^(id object, NSDictionary* bindings) + { + if (is_directory(object)) + return YES; + + return (BOOL)([regex numberOfMatchesInString:[object lastPathComponent] options:0 range:NSMakeRange(0, [[object lastPathComponent] length])] != 0); + }]]; + } + _list = [_list sortedArrayUsingComparator:^(id left, id right) { const BOOL left_is_dir = is_directory((NSString*)left); @@ -57,7 +88,7 @@ static BOOL is_directory(NSString* path) if(is_directory(path)) { - [[RetroArch_iOS get] pushViewController:[[RADirectoryList alloc] initWithPath:path]]; + [[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListWithPath:path]]; } else { diff --git a/ios/RetroArch/RAModuleList.m b/ios/RetroArch/RAModuleList.m index ccc784335c..c28e8c9c18 100644 --- a/ios/RetroArch/RAModuleList.m +++ b/ios/RetroArch/RAModuleList.m @@ -6,16 +6,6 @@ // Copyright (c) 2013 RetroArch. All rights reserved. // -static void display_error_alert(NSString* message) -{ - UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"RetroArch" - message:message - delegate:nil - cancelButtonTitle:@"OK" - otherButtonTitles:nil]; - [alert show]; -} - @implementation RAModuleList { NSMutableArray* _modules; @@ -38,7 +28,7 @@ static void display_error_alert(NSString* message) if (moduleList == nil || [moduleList count] == 0) { - display_error_alert(@"No libretro cores were found."); + [RetroArch_iOS displayErrorMessage:@"No libretro cores were found."]; } // Load the modules with their data @@ -62,7 +52,7 @@ static void display_error_alert(NSString* message) RAModuleInfo* info = (RAModuleInfo*)[_modules objectAtIndex:indexPath.row]; [RetroArch_iOS get].module_path = info.path; - [[RetroArch_iOS get] pushViewController:[[RADirectoryList alloc] initWithPath:nil]]; + [[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListWithPath:nil]]; } - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath diff --git a/ios/RetroArch/RetroArch_iOS.h b/ios/RetroArch/RetroArch_iOS.h index 6281a0014f..015155725b 100644 --- a/ios/RetroArch/RetroArch_iOS.h +++ b/ios/RetroArch/RetroArch_iOS.h @@ -12,6 +12,8 @@ extern NSString* const GSEventKeyUpNotification; @interface RetroArch_iOS : UIResponder ++ (void)displayErrorMessage:(NSString*)message; + + (RetroArch_iOS*)get; - (void)runGame:(NSString*)path; - (void)gameHasExited; diff --git a/ios/RetroArch/RetroArch_iOS.m b/ios/RetroArch/RetroArch_iOS.m index ba9b859d43..7c80bfdee6 100644 --- a/ios/RetroArch/RetroArch_iOS.m +++ b/ios/RetroArch/RetroArch_iOS.m @@ -27,6 +27,16 @@ extern uint32_t ios_current_touch_count; UINavigationController* _navigator; } ++ (void)displayErrorMessage:(NSString*)message +{ + UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"RetroArch" + message:message + delegate:nil + cancelButtonTitle:@"OK" + otherButtonTitles:nil]; + [alert show]; +} + + (RetroArch_iOS*)get { return (RetroArch_iOS*)[[UIApplication sharedApplication] delegate]; diff --git a/ios/RetroArch/views.h b/ios/RetroArch/views.h index ff8a6c5270..0469354ea9 100644 --- a/ios/RetroArch/views.h +++ b/ios/RetroArch/views.h @@ -20,10 +20,15 @@ @interface RAModuleList : UITableViewController @end -@interface RADirectoryList : UITableViewController +@interface RADirectoryFilterList : UITableViewController - (id)initWithPath:(NSString*)path; @end +@interface RADirectoryList : UITableViewController ++ (id)directoryListWithPath:(NSString*)path; +- (id)initWithPath:(NSString*)path filter:(NSRegularExpression*)regex; +@end + @interface RASettingsSubList : UITableViewController - (id)initWithSettings:(NSArray*)values title:(NSString*)title; - (void)writeSettings:(NSArray*)settingList toConfig:(config_file_t*)config;