add AutoSlow toggle, run in background and missing speed values, closes #3

This commit is contained in:
Jesús A. Álvarez 2016-06-06 16:09:23 +02:00
parent 9217b4ebcd
commit f46483c0b0
6 changed files with 157 additions and 17 deletions

View File

@ -6,6 +6,7 @@
// Copyright © 2016 namedfork. All rights reserved.
//
@import AVFoundation;
#import "AppDelegate.h"
#import "SettingsViewController.h"
#import "InsertDiskViewController.h"
@ -36,6 +37,7 @@ static NSObject<Emulator> *sharedEmulator = nil;
[self loadEmulator:@"MacPlus4M"];
}
[self initDefaults];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:NULL];
[sharedEmulator performSelector:@selector(run) withObject:nil afterDelay:0.1];
return YES;
}
@ -48,7 +50,10 @@ static NSObject<Emulator> *sharedEmulator = nil;
NSString *firstLanguage = [NSBundle preferredLocalizationsFromArray:layoutForLanguage.allKeys].firstObject;
NSDictionary *defaultValues = @{@"trackpad": @([UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPad),
@"keyboardLayout": layoutForLanguage[firstLanguage],
@"machine": @"MacPlus4M"
@"machine": @"MacPlus4M",
@"speedValue": @(sharedEmulator.initialSpeed),
@"runInBackground": @NO,
@"autoSlow": @(sharedEmulator.initialAutoSlow)
};
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
@ -59,8 +64,11 @@ static NSObject<Emulator> *sharedEmulator = nil;
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
if (object == [NSUserDefaults standardUserDefaults]) {
NSUserDefaults *defaults = object;
if ([keyPath isEqualToString:@"speedValue"]) {
sharedEmulator.speed = [[NSUserDefaults standardUserDefaults] integerForKey:@"speedValue"];
sharedEmulator.speed = [defaults integerForKey:@"speedValue"];
} else if ([keyPath isEqualToString:@"autoSlow"]) {
sharedEmulator.autoSlow = [defaults integerForKey:@"autoSlow"];
}
}
}
@ -87,15 +95,26 @@ static NSObject<Emulator> *sharedEmulator = nil;
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[NSUserDefaults standardUserDefaults] synchronize];
sharedEmulator.running = NO;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults synchronize];
if ([defaults boolForKey:@"runInBackground"]) {
// slow down to 1x when in background
sharedEmulator.speed = EmulatorSpeed1x;
} else {
sharedEmulator.running = NO;
}
if (sharedEmulator.anyDiskInserted == NO) {
exit(0);
}
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
sharedEmulator.running = YES;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (sharedEmulator.running) {
sharedEmulator.speed = [defaults integerForKey:@"speedValue"];
} else {
sharedEmulator.running = YES;
}
}
- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message {

View File

@ -64,6 +64,9 @@
<segment title="2x"/>
<segment title="4x"/>
<segment title="8x"/>
<segment title="16x"/>
<segment title="32x"/>
<segment title="∞"/>
</segments>
<connections>
<action selector="changeSpeed:" destination="WUA-f8-k8g" eventType="valueChanged" id="FDr-uw-7bN"/>
@ -169,6 +172,23 @@
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="toggle" textLabel="a1l-XI-MEz" style="IBUITableViewCellStyleDefault" id="1nB-54-Qfk">
<rect key="frame" x="0.0" y="313.5" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="1nB-54-Qfk" id="fZu-5X-Z4B">
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="a1l-XI-MEz">
<rect key="frame" x="15" y="0.0" width="570" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<sections/>
<connections>

View File

@ -10,11 +10,24 @@
@import CoreGraphics;
@import QuartzCore;
typedef enum : NSInteger {
EmulatorSpeedAllOut = -1,
EmulatorSpeed1x = 0,
EmulatorSpeed2x = 1,
EmulatorSpeed4x = 2,
EmulatorSpeed8x = 3,
EmulatorSpeed16x = 4,
EmulatorSpeed32x = 5
} EmulatorSpeed;
@protocol Emulator <NSObject>
@property (nonatomic, strong) NSString *dataPath;
@property (nonatomic, assign, getter=isRunning) BOOL running;
@property (nonatomic, assign) NSInteger speed;
@property (nonatomic, assign) EmulatorSpeed speed;
@property (nonatomic, assign) BOOL autoSlow;
@property (nonatomic, readonly) BOOL initialAutoSlow;
@property (nonatomic, readonly) BOOL autoSlowSupported;
@property (nonatomic, weak) CALayer *screenLayer;
@property (nonatomic, readonly) NSBundle *bundle;

View File

@ -77,6 +77,10 @@
<string>3</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchStoryboardName</key>

View File

@ -1757,14 +1757,40 @@ static dispatch_once_t onceToken;
return [NSBundle bundleForClass:self.class];
}
- (NSInteger)speed {
- (EmulatorSpeed)speed {
return SpeedValue;
}
- (void)setSpeed:(NSInteger)speed {
- (void)setSpeed:(EmulatorSpeed)speed {
SpeedValue = speed;
}
#if EnableAutoSlow
- (BOOL)autoSlow {
return !WantNotAutoSlow;
}
- (void)setAutoSlow:(BOOL)autoSlow {
WantNotAutoSlow = !autoSlow;
}
#else
- (BOOL)autoSlow {
return NO;
}
- (void)setAutoSlow:(BOOL)autoSlow {
}
#endif
- (BOOL)autoSlowSupported {
return EnableAutoSlow;
}
- (BOOL)initialAutoSlow {
return !WantInitNotAutoSlow;
}
- (BOOL)isRunning {
return !SpeedStopped;
}
@ -1803,7 +1829,9 @@ static dispatch_once_t onceToken;
}
- (void)updateScreen:(CGImageRef)screenImage {
screenLayer.contents = (__bridge id)screenImage;
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
screenLayer.contents = (__bridge id)screenImage;
}
}
#pragma mark - Disk

View File

@ -25,6 +25,7 @@ typedef enum : NSInteger {
{
NSArray *keyboardLayouts;
NSArray<NSBundle*> *emulatorBundles;
NSBundle *selectedEmulatorBundle;
NSString *aboutTitle;
NSArray<NSDictionary<NSString*,NSString*>*> *aboutItems;
UITextView *footerView;
@ -33,10 +34,21 @@ typedef enum : NSInteger {
- (void)viewDidLoad {
[super viewDidLoad];
keyboardLayouts = [[NSBundle mainBundle] pathsForResourcesOfType:@"nfkeyboardlayout" inDirectory:@"Keyboard Layouts"];
emulatorBundles = [AppDelegate sharedInstance].emulatorBundles;
[self loadEmulatorBundles];
[self loadCredits];
}
- (void)loadEmulatorBundles {
emulatorBundles = [AppDelegate sharedInstance].emulatorBundles;
NSString *selectedBundleName = [[NSUserDefaults standardUserDefaults] stringForKey:@"machine"];
for (NSBundle *bundle in emulatorBundles) {
NSString *bundleName = bundle.bundlePath.lastPathComponent.stringByDeletingPathExtension;
if ([selectedBundleName isEqualToString:bundleName]) {
selectedEmulatorBundle = bundle;
}
}
}
- (void)loadCredits {
NSDictionary *aboutData = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"about" ofType:@"plist"]];
aboutTitle = aboutData[@"title"];
@ -76,7 +88,8 @@ typedef enum : NSInteger {
- (IBAction)changeSpeed:(UISegmentedControl*)sender {
if ([sender isKindOfClass:[UISegmentedControl class]]) {
[[NSUserDefaults standardUserDefaults] setInteger:sender.selectedSegmentIndex forKey:@"speedValue"];
EmulatorSpeed speedValue = sender.selectedSegmentIndex == sender.numberOfSegments - 1 ? EmulatorSpeedAllOut : sender.selectedSegmentIndex;
[[NSUserDefaults standardUserDefaults] setInteger:speedValue forKey:@"speedValue"];
}
}
@ -86,6 +99,18 @@ typedef enum : NSInteger {
}
}
- (void)changeRunInBackground:(UISwitch*)sender {
if ([sender isKindOfClass:[UISwitch class]]) {
[[NSUserDefaults standardUserDefaults] setBool:sender.on forKey:@"runInBackground"];
}
}
- (void)changeAutoSlow:(UISwitch*)sender {
if ([sender isKindOfClass:[UISwitch class]]) {
[[NSUserDefaults standardUserDefaults] setBool:sender.on forKey:@"autoSlow"];
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
@ -94,6 +119,11 @@ typedef enum : NSInteger {
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
switch (section) {
case SettingsSectionSpeed: {
NSDictionary *capabilities = [selectedEmulatorBundle objectForInfoDictionaryKey:@"MNVMCapabilities"];
BOOL hasAutoSlow = [capabilities[@"AutoSlow"] boolValue];
return hasAutoSlow ? 3 : 2;
}
case SettingsSectionKeyboard:
return keyboardLayouts.count;
case SettingsSectionMachine:
@ -130,7 +160,9 @@ typedef enum : NSInteger {
}
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
if (section == SettingsSectionMachine) {
if (section == SettingsSectionSpeed) {
return NSLocalizedString(@"Faster speeds and running in background drain the battery faster", nil);
} else if (section == SettingsSectionMachine) {
return NSLocalizedString(@"Changing the emulated machine requires to relaunch Mini vMac", nil);
} else {
return nil;
@ -150,9 +182,18 @@ typedef enum : NSInteger {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSInteger section = indexPath.section;
if (section == SettingsSectionSpeed) {
cell = [tableView dequeueReusableCellWithIdentifier:@"speed" forIndexPath:indexPath];
UISegmentedControl *speedControl = (UISegmentedControl*)[cell viewWithTag:128];
speedControl.selectedSegmentIndex = [defaults integerForKey:@"speedValue"];
if (indexPath.row == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:@"speed" forIndexPath:indexPath];
UISegmentedControl *speedControl = (UISegmentedControl*)[cell viewWithTag:128];
EmulatorSpeed speedValue = [defaults integerForKey:@"speedValue"];
speedControl.selectedSegmentIndex = speedValue == EmulatorSpeedAllOut ? speedControl.numberOfSegments - 1 : speedValue;
} else if (indexPath.row == 1) {
cell = [self switchCellForTableView:tableView indexPath:indexPath action:@selector(changeRunInBackground:) on:[defaults boolForKey:@"runInBackground"]];
cell.textLabel.text = NSLocalizedString(@"Run in background", nil);
} else if (indexPath.row == 2) {
cell = [self switchCellForTableView:tableView indexPath:indexPath action:@selector(changeAutoSlow:) on:[defaults boolForKey:@"autoSlow"]];
cell.textLabel.text = NSLocalizedString(@"AutoSlow", nil);
}
} else if (section == SettingsSectionMouse) {
cell = [tableView dequeueReusableCellWithIdentifier:@"mouse" forIndexPath:indexPath];
UISegmentedControl *mouseControl = (UISegmentedControl*)[cell viewWithTag:128];
@ -171,8 +212,7 @@ typedef enum : NSInteger {
cell.detailTextLabel.text = [bundle objectForInfoDictionaryKey:@"CFBundleGetInfoString"];
NSString *iconName = [NSString stringWithFormat:@"PlugIns/%@.mnvm/Icon", bundleName];
cell.imageView.image = [UIImage imageNamed:iconName];
BOOL selected = [[defaults stringForKey:@"machine"] isEqualToString:bundleName];
cell.accessoryType = selected ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
cell.accessoryType = bundle == selectedEmulatorBundle ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
} else if (section == SettingsSectionAbout) {
cell = [tableView dequeueReusableCellWithIdentifier:@"about" forIndexPath:indexPath];
NSDictionary<NSString*,NSString*> *item = aboutItems[indexPath.row];
@ -203,6 +243,8 @@ typedef enum : NSInteger {
NSBundle *bundle = emulatorBundles[indexPath.row];
NSString *bundleName = bundle.bundlePath.lastPathComponent.stringByDeletingPathExtension;
[defaults setValue:bundleName forKey:@"machine"];
selectedEmulatorBundle = bundle;
[tableView reloadSections:[NSIndexSet indexSetWithIndex:SettingsSectionSpeed] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationAutomatic];
} else if (indexPath.section == SettingsSectionAbout) {
// links in about
@ -213,4 +255,18 @@ typedef enum : NSInteger {
}
}
- (UITableViewCell*)switchCellForTableView:(UITableView*)tableView indexPath:(NSIndexPath*)indexPath action:(SEL)action on:(BOOL)on {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"toggle" forIndexPath:indexPath];
UISwitch *cellSwitch = (UISwitch*)cell.accessoryView;
if (cellSwitch == nil) {
cellSwitch = [UISwitch new];
cell.accessoryView = cellSwitch;
} else {
[cellSwitch removeTarget:nil action:nil forControlEvents:UIControlEventAllEvents];
}
cellSwitch.on = on;
[cellSwitch addTarget:self action:action forControlEvents:UIControlEventValueChanged];
return cell;
}
@end