From b0329be296c42192e3eb4eb0a55733d094fdbd06 Mon Sep 17 00:00:00 2001 From: meancoot Date: Tue, 26 Mar 2013 22:38:38 -0400 Subject: [PATCH] (iOS) Cache the RAModuleInfo structures instead of reloading the each time a RAModuleList is created. --- ios/RetroArch.xcodeproj/project.pbxproj | 6 ++ ios/RetroArch/RAModuleInfo.h | 31 +++++++++ ios/RetroArch/RAModuleInfo.m | 83 +++++++++++++++++++++++++ ios/RetroArch/RAModuleInfoList.m | 39 ------------ ios/RetroArch/browser/RAModuleList.m | 65 +++++++------------ ios/RetroArch/settings/RASettingsList.m | 4 +- ios/RetroArch/views.h | 17 +---- 7 files changed, 144 insertions(+), 101 deletions(-) create mode 100644 ios/RetroArch/RAModuleInfo.h create mode 100644 ios/RetroArch/RAModuleInfo.m diff --git a/ios/RetroArch.xcodeproj/project.pbxproj b/ios/RetroArch.xcodeproj/project.pbxproj index 1d74a55fff..8806ae1fe9 100644 --- a/ios/RetroArch.xcodeproj/project.pbxproj +++ b/ios/RetroArch.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 9605EA9B170288EA001D47B0 /* RAModuleInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9605EA9A170288EA001D47B0 /* RAModuleInfo.m */; }; 96096DD816D1ABAF00BF4499 /* RAModuleInfoList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */; }; 962979F616C43B9500E6DCE0 /* ic_dir.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F416C43B9500E6DCE0 /* ic_dir.png */; }; 962979F716C43B9500E6DCE0 /* ic_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F516C43B9500E6DCE0 /* ic_file.png */; }; @@ -46,6 +47,8 @@ /* Begin PBXFileReference section */ 960356BC1700652C008F55DA /* btpad_ps3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = btpad_ps3.c; sourceTree = ""; }; 960356BD1700652C008F55DA /* btpad_wii.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = btpad_wii.c; sourceTree = ""; }; + 9605EA99170288EA001D47B0 /* RAModuleInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RAModuleInfo.h; sourceTree = ""; }; + 9605EA9A170288EA001D47B0 /* RAModuleInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAModuleInfo.m; sourceTree = ""; }; 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAModuleInfoList.m; sourceTree = ""; }; 9614C71F16DDC018000B36EF /* RetroArch copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "RetroArch copy-Info.plist"; path = "/Users/jason/Documents/Projects/ios/RetroArch/ios/RetroArch copy-Info.plist"; sourceTree = ""; }; 962979F416C43B9500E6DCE0 /* ic_dir.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_dir.png; path = "../../android/phoenix/res/drawable-xhdpi/ic_dir.png"; sourceTree = ""; }; @@ -256,6 +259,8 @@ 96297A0E16C5AEA100E6DCE0 /* main.m */, 963F5AC516CC523B009BBD19 /* RAGameView.m */, 96F9C28216FFA55F002455B3 /* RALogView.m */, + 9605EA9A170288EA001D47B0 /* RAModuleInfo.m */, + 9605EA99170288EA001D47B0 /* RAModuleInfo.h */, 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */, 96C19C2616D455BE00FE8D5A /* rarch_wrapper.h */, 96297A0A16C5AD8D00E6DCE0 /* RetroArch_iOS.h */, @@ -411,6 +416,7 @@ 966B9CB416E41C07005B61E1 /* RAModuleList.m in Sources */, D48581DE16F823F9004BEB17 /* griffin.c in Sources */, 96F9C28316FFA55F002455B3 /* RALogView.m in Sources */, + 9605EA9B170288EA001D47B0 /* RAModuleInfo.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/RetroArch/RAModuleInfo.h b/ios/RetroArch/RAModuleInfo.h new file mode 100644 index 0000000000..5f18be5f6e --- /dev/null +++ b/ios/RetroArch/RAModuleInfo.h @@ -0,0 +1,31 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2013 - Jason Fetters + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "conf/config_file.h" + +@interface RAModuleInfo : NSObject +@property (strong) NSString* path; +@property config_file_t* data; +@property (strong) NSString* configPath; +@property (strong) NSString* displayName; +@property (strong) NSArray* supportedExtensions; + ++ (NSArray*)getModules; +- (bool)supportsFileAtPath:(NSString*)path; +@end + +@interface RAModuleInfoList : UITableViewController +- (id)initWithModuleInfo:(RAModuleInfo*)info; +@end diff --git a/ios/RetroArch/RAModuleInfo.m b/ios/RetroArch/RAModuleInfo.m new file mode 100644 index 0000000000..217f8eca68 --- /dev/null +++ b/ios/RetroArch/RAModuleInfo.m @@ -0,0 +1,83 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2013 - Jason Fetters + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#import "RAModuleInfo.h" + +static NSMutableArray* moduleList; + +@implementation RAModuleInfo ++ (NSArray*)getModules +{ + if (!moduleList) + { + char pattern[PATH_MAX]; + snprintf(pattern, PATH_MAX, "%s/modules/*.dylib", [[NSBundle mainBundle].bundlePath UTF8String]); + + glob_t files = {0}; + glob(pattern, 0, 0, &files); + + moduleList = [NSMutableArray arrayWithCapacity:files.gl_pathc]; + + for (int i = 0; i != files.gl_pathc; i ++) + { + RAModuleInfo* newInfo = [RAModuleInfo new]; + newInfo.path = [NSString stringWithUTF8String:files.gl_pathv[i]]; + + strcpy(pattern, files.gl_pathv[i]); + strcpy(strrchr(pattern, '.'), ".info"); + newInfo.data = config_file_new(pattern); + + char* dispname = 0; + char* extensions = 0; + + if (newInfo.data) + { + config_get_string(newInfo.data, "display_name", &dispname); + config_get_string(newInfo.data, "supported_extensions", &extensions); + } + + newInfo.configPath = [NSString stringWithFormat:@"%@/%@.cfg", [RetroArch_iOS get].system_directory, [[newInfo.path lastPathComponent] stringByDeletingPathExtension]]; + newInfo.displayName = dispname ? [NSString stringWithUTF8String:dispname] : [[newInfo.path lastPathComponent] stringByDeletingPathExtension]; + newInfo.supportedExtensions = extensions ? [[NSString stringWithUTF8String:extensions] componentsSeparatedByString:@"|"] : [NSArray array]; + + free(dispname); + free(extensions); + + [moduleList addObject:newInfo]; + } + + globfree(&files); + + [moduleList sortUsingComparator:^(RAModuleInfo* left, RAModuleInfo* right) + { + return [left.displayName caseInsensitiveCompare:right.displayName]; + }]; + } + + return moduleList; +} + +- (void)dealloc +{ + config_file_free(self.data); +} + +- (bool)supportsFileAtPath:(NSString*)path +{ + return [self.supportedExtensions containsObject:[[path pathExtension] lowercaseString]]; +} + +@end diff --git a/ios/RetroArch/RAModuleInfoList.m b/ios/RetroArch/RAModuleInfoList.m index 6be73622d2..590f0d656b 100644 --- a/ios/RetroArch/RAModuleInfoList.m +++ b/ios/RetroArch/RAModuleInfoList.m @@ -13,45 +13,6 @@ * If not, see . */ -@implementation RAModuleInfo -+ (RAModuleInfo*)moduleWithPath:(NSString*)thePath data:(config_file_t*)theData -{ - RAModuleInfo* new = [RAModuleInfo new]; - - char* dispname = 0; - char* extensions = 0; - - if (theData) - { - config_get_string(theData, "display_name", &dispname); - config_get_string(theData, "supported_extensions", &extensions); - } - - new.displayName = dispname ? [NSString stringWithUTF8String:dispname] : [[thePath lastPathComponent] stringByDeletingPathExtension]; - new.path = thePath; - new.configPath = [NSString stringWithFormat:@"%@/%@.cfg", [RetroArch_iOS get].system_directory, [[thePath lastPathComponent] stringByDeletingPathExtension]]; - new.data = theData; - - new.supportedExtensions = extensions ? [[NSString stringWithUTF8String:extensions] componentsSeparatedByString:@"|"] : [NSArray array]; - - free(dispname); - free(extensions); - - return new; -} - -- (void)dealloc -{ - config_file_free(self.data); -} - -- (bool)supportsFileAtPath:(NSString*)path -{ - return [self.supportedExtensions containsObject:[[path pathExtension] lowercaseString]]; -} - -@end - static NSString* const labels[3] = {@"Emulator Name", @"Manufacturer", @"Name"}; static const char* const keys[3] = {"emuname", "manufacturer", "systemname"}; static NSString* const sectionNames[2] = {@"Emulator", @"Hardware"}; diff --git a/ios/RetroArch/browser/RAModuleList.m b/ios/RetroArch/browser/RAModuleList.m index 6d0bbb168f..ba524cc649 100644 --- a/ios/RetroArch/browser/RAModuleList.m +++ b/ios/RetroArch/browser/RAModuleList.m @@ -13,6 +13,7 @@ * If not, see . */ +#import "RAMOduleInfo.h" #import "browser.h" @implementation RAModuleList @@ -26,56 +27,37 @@ - (id)initWithGame:(NSString*)path { self = [super initWithStyle:UITableViewStyleGrouped]; + [self setTitle:[path lastPathComponent]]; + _game = path; - // Get the contents of the modules directory of the bundle. - NSString* module_dir = [NSString stringWithFormat:@"%@/modules", [[NSBundle mainBundle] bundlePath]]; + // + NSArray* moduleList = [RAModuleInfo getModules]; - NSArray* moduleList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:module_dir error:nil]; - - if (moduleList != nil) - { - moduleList = [module_dir stringsByAppendingPaths:moduleList]; - moduleList = [moduleList pathsMatchingExtensions:[NSArray arrayWithObject:@"dylib"]]; - } - - if (moduleList == nil || [moduleList count] == 0) - { + if (moduleList.count == 0) [RetroArch_iOS displayErrorMessage:@"No libretro cores were found."]; - } - + // Load the modules with their data _supported = [NSMutableArray array]; _other = [NSMutableArray array]; - for (int i = 0; i != [moduleList count]; i ++) + for (RAModuleInfo* i in moduleList) { - NSString* modulePath = [moduleList objectAtIndex:i]; - NSString* baseName = [[modulePath stringByDeletingPathExtension] stringByAppendingPathExtension:@"info"]; - - RAModuleInfo* module = [RAModuleInfo moduleWithPath:modulePath data:config_file_new([baseName UTF8String])]; - - if ([module supportsFileAtPath:_game]) - [_supported addObject:module]; - else - [_other addObject:module]; + NSMutableArray* target = [i supportsFileAtPath:_game] ? _supported : _other; + [target addObject:i]; } - // Sort - [_supported sortUsingComparator:^(RAModuleInfo* left, RAModuleInfo* right) - { - return [left.displayName caseInsensitiveCompare:right.displayName]; - }]; + // No sort, [RAModuleInfo getModules] is already sorted by display name - [_other sortUsingComparator:^(RAModuleInfo* left, RAModuleInfo* right) - { - return [left.displayName caseInsensitiveCompare:right.displayName]; - }]; - - [self setTitle:[_game lastPathComponent]]; return self; } +- (RAModuleInfo*)moduleInfoForIndexPath:(NSIndexPath*)path +{ + NSMutableArray* sectionData = (_supported.count && path.section == 0) ? _supported : _other; + return (RAModuleInfo*)sectionData[path.row]; +} + - (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView { return _supported.count ? 2 : 1; @@ -97,27 +79,22 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - NSMutableArray* sectionData = (_supported.count && indexPath.section == 0) ? _supported : _other; - [RetroArch_iOS get].moduleInfo = (RAModuleInfo*)sectionData[indexPath.row]; - + [RetroArch_iOS get].moduleInfo = [self moduleInfoForIndexPath:indexPath]; [[RetroArch_iOS get] runGame:_game]; } - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { - NSMutableArray* sectionData = (_supported.count && indexPath.section == 0) ? _supported : _other; - [RetroArch_iOS get].moduleInfo = (RAModuleInfo*)sectionData[indexPath.row]; - + [RetroArch_iOS get].moduleInfo = [self moduleInfoForIndexPath:indexPath]; [[RetroArch_iOS get] showSettings]; } - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"module"]; - cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"module"]; + cell = (cell) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"module"]; - NSMutableArray* sectionData = (_supported.count && indexPath.section == 0) ? _supported : _other; - RAModuleInfo* info = (RAModuleInfo*)sectionData[indexPath.row]; + RAModuleInfo* info = [self moduleInfoForIndexPath:indexPath]; cell.textLabel.text = info.displayName; cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; diff --git a/ios/RetroArch/settings/RASettingsList.m b/ios/RetroArch/settings/RASettingsList.m index c5148ce2cc..e62ab76449 100644 --- a/ios/RetroArch/settings/RASettingsList.m +++ b/ios/RetroArch/settings/RASettingsList.m @@ -133,9 +133,9 @@ static RASettingData* custom_action(NSString* action) (void)[[RASettingsList alloc] init]; } -- (id)init +- (RASettingsList*)initWithModule:(RAModuleInfo*)module { - config_file_t* config = config_file_new([[RetroArch_iOS get].moduleInfo.configPath UTF8String]); + config_file_t* config = config_file_new([module.configPath UTF8String]); NSString* overlay_path = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/overlays/"]; NSString* shader_path = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/shaders/"]; diff --git a/ios/RetroArch/views.h b/ios/RetroArch/views.h index 2ed07b7fab..cc619d5c6b 100644 --- a/ios/RetroArch/views.h +++ b/ios/RetroArch/views.h @@ -16,7 +16,7 @@ #import #import -#include "conf/config_file.h" +#import "RAModuleInfo.h" @interface RAGameView : UIViewController + (RAGameView*)get; @@ -26,18 +26,3 @@ @interface RALogView : UITableViewController @end - -@interface RAModuleInfo : NSObject -@property (strong) NSString* displayName; -@property (strong) NSString* path; -@property (strong) NSString* configPath; -@property config_file_t* data; -@property (strong) NSArray* supportedExtensions; - -+ (RAModuleInfo*)moduleWithPath:(NSString*)thePath data:(config_file_t*)theData; -- (bool)supportsFileAtPath:(NSString*)path; -@end - -@interface RAModuleInfoList : UITableViewController -- (id)initWithModuleInfo:(RAModuleInfo*)info; -@end