Basic database access is working

This commit is contained in:
Cameron Gutman 2015-12-02 00:25:38 -08:00
parent fe616d86c5
commit 3076e29335
13 changed files with 274 additions and 118 deletions

View File

@ -13,15 +13,14 @@
+ (NSString*) getUniqueId {
DataManager* dataMan = [[DataManager alloc] init];
Settings* prefs = [dataMan retrieveSettings];
NSString* uniqueId = prefs.uniqueId;
NSString* uniqueId = [dataMan getUniqueId];
if (uniqueId == nil) {
uniqueId = [IdManager generateUniqueId];
prefs.uniqueId = uniqueId;
[dataMan saveData];
[dataMan updateUniqueId:uniqueId];
Log(LOG_I, @"No UUID found. Generated new UUID: %@", uniqueId);
}
return uniqueId;
}

View File

@ -7,23 +7,22 @@
//
#import <Foundation/Foundation.h>
#import "Settings.h"
#import "AppDelegate.h"
#import "Host.h"
#import "App.h"
#import "TemporaryHost.h"
#import "TemporaryApp.h"
#import "TemporarySettings.h"
@interface DataManager : NSObject
@property (strong, nonatomic) AppDelegate* appDelegate;
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls;
- (Settings*) retrieveSettings;
- (NSArray*) retrieveHosts;
- (void) saveData;
- (Host*) createHost;
- (void) removeHost:(Host*)host;
- (App*) addAppFromTemporaryApp:(TemporaryApp*)tempApp;
- (void) removeAppFromHost:(App*)app;
- (NSArray*) getHosts;
- (void) updateHost:(TemporaryHost*)host;
- (void) removeHost:(TemporaryHost*)host;
- (TemporarySettings*) getSettings;
- (void) updateUniqueId:(NSString*)uniqueId;
- (NSString*) getUniqueId;
@end

View File

@ -8,45 +8,87 @@
#import "DataManager.h"
#import "TemporaryApp.h"
#import "TemporarySettings.h"
#import "Settings.h"
@implementation DataManager
+ (NSObject *)databaseLock {
static NSObject *lock = nil;
if (lock == nil) {
lock = [[NSObject alloc] init];
}
return lock;
@implementation DataManager {
NSManagedObjectContext *_managedObjectContext;
AppDelegate *_appDelegate;
}
- (id) init {
self = [super init];
self.appDelegate = [[UIApplication sharedApplication] delegate];
_appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:_appDelegate.persistentStoreCoordinator];
return self;
}
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls {
Settings* settingsToSave = [self retrieveSettings];
settingsToSave.framerate = [NSNumber numberWithInteger:framerate];
// Bitrate is persisted in kbps
settingsToSave.bitrate = [NSNumber numberWithInteger:bitrate];
settingsToSave.height = [NSNumber numberWithInteger:height];
settingsToSave.width = [NSNumber numberWithInteger:width];
settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls];
- (void) updateUniqueId:(NSString*)uniqueId {
[_managedObjectContext performBlockAndWait:^{
[self retrieveSettings].uniqueId = uniqueId;
[self saveData];
}];
}
NSError* error;
if (![[self.appDelegate managedObjectContext] save:&error]) {
Log(LOG_E, @"Unable to save settings to database: %@", error);
}
[self.appDelegate saveContext];
- (NSString*) getUniqueId {
__block NSString *uid;
[_managedObjectContext performBlockAndWait:^{
uid = [self retrieveSettings].uniqueId;
}];
return uid;
}
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls {
[_managedObjectContext performBlockAndWait:^{
Settings* settingsToSave = [self retrieveSettings];
settingsToSave.framerate = [NSNumber numberWithInteger:framerate];
// Bitrate is persisted in kbps
settingsToSave.bitrate = [NSNumber numberWithInteger:bitrate];
settingsToSave.height = [NSNumber numberWithInteger:height];
settingsToSave.width = [NSNumber numberWithInteger:width];
settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls];
[self saveData];
}];
}
- (void) updateHost:(TemporaryHost *)host {
[_managedObjectContext performBlockAndWait:^{
// Add a new persistent managed object if one doesn't exist
if (host.parent == nil) {
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:_managedObjectContext];
host.parent = [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext];
}
// Push changes from the temp host to the persistent one
[host propagateChangesToParent];
[self saveData];
}];
}
- (TemporarySettings*) getSettings {
__block TemporarySettings *tempSettings;
[_managedObjectContext performBlockAndWait:^{
tempSettings = [[TemporarySettings alloc] initFromSettings:[self retrieveSettings]];
}];
return tempSettings;
}
- (Settings*) retrieveSettings {
NSArray* fetchedRecords = [self fetchRecords:@"Settings"];
if (fetchedRecords.count == 0) {
// create a new settings object with the default values
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:[self.appDelegate managedObjectContext]];
Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:_managedObjectContext];
Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext];
return settings;
} else {
@ -55,74 +97,51 @@
}
}
- (Host*) createHost {
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:[self.appDelegate managedObjectContext]];
return [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
}
- (void) removeHost:(Host*)host {
[[self.appDelegate managedObjectContext] deleteObject:host];
[self saveData];
- (void) removeHost:(TemporaryHost*)host {
if (host.parent == nil) {
// Not inserted into the DB
return;
}
[_managedObjectContext performBlockAndWait:^{
[_managedObjectContext deleteObject:host.parent];
[self saveData];
}];
}
- (void) saveData {
@synchronized([DataManager databaseLock]) {
NSError* error;
if (![[self.appDelegate managedObjectContext] save:&error]) {
Log(LOG_E, @"Unable to save hosts to database: %@", error);
NSError* error;
if (![_managedObjectContext save:&error]) {
Log(LOG_E, @"Unable to save hosts to database: %@", error);
}
[_appDelegate saveContext];
}
- (NSArray*) getHosts {
__block NSMutableArray *tempHosts = [[NSMutableArray alloc] init];
[_managedObjectContext performBlockAndWait:^{
NSArray *hosts = [self fetchRecords:@"Host"];
for (Host* host in hosts) {
[tempHosts addObject:[[TemporaryHost alloc] initFromHost:host]];
}
[self.appDelegate saveContext];
}
}
- (NSArray*) retrieveHosts {
return [self fetchRecords:@"Host"];
}
- (App*) addAppFromTemporaryApp:(TemporaryApp*)tempApp {
}];
App* managedApp;
@synchronized([DataManager databaseLock]) {
NSEntityDescription* entity = [NSEntityDescription entityForName:@"App" inManagedObjectContext:[self.appDelegate managedObjectContext]];
managedApp = [[App alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
assert(tempApp.host != nil);
managedApp.id = tempApp.id;
managedApp.image = tempApp.image;
managedApp.name = tempApp.name;
managedApp.isRunning = tempApp.isRunning;
managedApp.host = tempApp.host;
[managedApp.host addAppListObject:managedApp];
}
return managedApp;
}
- (void) removeAppFromHost:(App*)app {
@synchronized([DataManager databaseLock]) {
assert(app.host != nil);
[app.host removeAppListObject:app];
[[self.appDelegate managedObjectContext] deleteObject:app];
}
return tempHosts;
}
- (NSArray*) fetchRecords:(NSString*)entityName {
NSArray* fetchedRecords;
@synchronized([DataManager databaseLock]) {
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:[self.appDelegate managedObjectContext]];
[fetchRequest setEntity:entity];
[fetchRequest setAffectedStores:[NSArray arrayWithObjects:[[self.appDelegate persistentStoreCoordinator] persistentStoreForURL:[self.appDelegate getStoreURL]], nil]];
NSError* error;
fetchedRecords = [[self.appDelegate managedObjectContext] executeFetchRequest:fetchRequest error:&error];
//TODO: handle errors
}
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:_managedObjectContext];
[fetchRequest setEntity:entity];
NSError* error;
fetchedRecords = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
//TODO: handle errors
return fetchedRecords;
}

View File

@ -8,6 +8,7 @@
#import <Foundation/Foundation.h>
#import "TemporaryHost.h"
#import "App.h"
@interface TemporaryApp : NSObject
@ -17,10 +18,16 @@
@property (nonatomic) BOOL isRunning;
@property (nullable, nonatomic, retain) TemporaryHost *host;
@property (nullable, nonatomic) App* parent;
NS_ASSUME_NONNULL_BEGIN
- (id) initFromApp:(App*)app withTempHost:(TemporaryHost*)tempHost;
- (NSComparisonResult)compareName:(TemporaryApp *)other;
- (void) propagateChangesToParent;
NS_ASSUME_NONNULL_END
@end

View File

@ -7,9 +7,30 @@
//
#import "TemporaryApp.h"
#import "App.h"
@implementation TemporaryApp
- (id) initFromApp:(App*)app withTempHost:(TemporaryHost*)tempHost {
self = [self init];
self.parent = app;
self.id = app.id;
self.image = app.image;
self.name = app.name;
self.host = tempHost;
return self;
}
- (void) propagateChangesToParent {
self.parent.id = self.id;
self.parent.image = self.image;
self.parent.name = self.name;
self.parent.host = self.host.parent;
}
- (NSComparisonResult)compareName:(TemporaryApp *)other {
return [self.name caseInsensitiveCompare:other.name];
}

View File

@ -8,6 +8,7 @@
#import <Foundation/Foundation.h>
#import "Utils.h"
#import "Host.h"
@interface TemporaryHost : NSObject
@ -15,18 +16,24 @@
@property (nonatomic) PairState pairState;
@property (nonatomic, nullable) NSString * activeAddress;
@property (nullable, nonatomic, retain) NSString *address;
@property (nullable, nonatomic, retain) NSString *externalAddress;
@property (nullable, nonatomic, retain) NSString *localAddress;
@property (nullable, nonatomic, retain) NSString *mac;
@property (nullable, nonatomic, retain) NSString *name;
@property (nullable, nonatomic, retain) NSString *uuid;
@property (nullable, nonatomic, retain) NSSet *appList;
@property (nullable, nonatomic) Host* parent;
NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, retain) NSString *address;
@property (nonatomic, retain) NSString *externalAddress;
@property (nonatomic, retain) NSString *localAddress;
@property (nonatomic, retain) NSString *mac;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *uuid;
@property (nonatomic, retain) NSSet *appList;
- (id) initFromHost:(Host*)host;
- (NSComparisonResult)compareName:(TemporaryHost *)other;
- (void) propagateChangesToParent;
NS_ASSUME_NONNULL_END
@end

View File

@ -7,9 +7,60 @@
//
#import "TemporaryHost.h"
#import "Host.h"
#import "TemporaryApp.h"
#import "App.h"
@implementation TemporaryHost
- (id) initFromHost:(Host*)host {
self = [self init];
self.parent = host;
self.address = host.address;
self.externalAddress = host.externalAddress;
self.localAddress = host.localAddress;
self.mac = host.mac;
self.name = host.name;
self.uuid = host.uuid;
NSMutableSet *appList = [[NSMutableSet alloc] init];
for (App* app in host.appList) {
TemporaryApp *tempApp = [[TemporaryApp alloc] initFromApp:app withTempHost:self];
[appList addObject:tempApp];
}
self.appList = appList;
return self;
}
- (void) propagateChangesToParent {
self.parent.address = self.address;
self.parent.externalAddress = self.externalAddress;
self.parent.localAddress = self.localAddress;
self.parent.mac = self.mac;
self.parent.name = self.name;
self.parent.uuid = self.uuid;
NSMutableSet *applist = [[NSMutableSet alloc] init];
for (TemporaryApp* app in self.appList) {
// Add a new persistent managed object if one doesn't exist
if (app.parent == nil) {
NSEntityDescription* entity = [NSEntityDescription entityForName:@"App" inManagedObjectContext:self.parent.managedObjectContext];
app.parent = [[App alloc] initWithEntity:entity insertIntoManagedObjectContext:self.parent.managedObjectContext];
}
[app propagateChangesToParent];
[applist addObject:app.parent];
}
self.parent.appList = applist;
}
- (NSComparisonResult)compareName:(TemporaryHost *)other {
return [self.name caseInsensitiveCompare:other.name];
}

View File

@ -0,0 +1,25 @@
//
// TemporarySettings.h
// Moonlight
//
// Created by Cameron Gutman on 12/1/15.
// Copyright © 2015 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Settings.h"
@interface TemporarySettings : NSObject
@property (nonatomic, retain) Settings * parent;
@property (nonatomic, retain) NSNumber * bitrate;
@property (nonatomic, retain) NSNumber * framerate;
@property (nonatomic, retain) NSNumber * height;
@property (nonatomic, retain) NSNumber * width;
@property (nonatomic, retain) NSNumber * onscreenControls;
@property (nonatomic, retain) NSString * uniqueId;
- (id) initFromSettings:(Settings*)settings;
@end

View File

@ -0,0 +1,28 @@
//
// TemporarySettings.m
// Moonlight
//
// Created by Cameron Gutman on 12/1/15.
// Copyright © 2015 Moonlight Stream. All rights reserved.
//
#import "TemporarySettings.h"
@implementation TemporarySettings
- (id) initFromSettings:(Settings*)settings {
self = [self init];
self.parent = settings;
self.bitrate = settings.bitrate;
self.framerate = settings.framerate;
self.height = settings.height;
self.width = settings.width;
self.onscreenControls = settings.onscreenControls;
self.uniqueId = settings.uniqueId;
return self;
}
@end

View File

@ -32,7 +32,7 @@
- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport swipeDelegate:(id<EdgeDetectionDelegate>)swipeDelegate {
onScreenControls = [[OnScreenControls alloc] initWithView:self controllerSup:controllerSupport swipeDelegate:swipeDelegate];
DataManager* dataMan = [[DataManager alloc] init];
OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan retrieveSettings].onscreenControls integerValue];
OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan getSettings].onscreenControls integerValue];
if (level == OnScreenControlsLevelAuto) {
[controllerSupport initAutoOnScreenControlMode:onScreenControls];

View File

@ -17,7 +17,7 @@
#import "UIAppView.h"
#import "SettingsViewController.h"
#import "DataManager.h"
#import "Settings.h"
#import "TemporarySettings.h"
#import "WakeOnLanManager.h"
#import "AppListResponse.h"
#import "ServerInfoResponse.h"
@ -162,15 +162,12 @@ static NSMutableSet* hostList;
DataManager* database = [[DataManager alloc] init];
host.appList = newList;
[database updateHost:host];
[database saveData];
}
- (void)showHostSelectionView {
[_appManager stopRetrieving];
[[[DataManager alloc] init] saveData];
_selectedHost = nil;
_computerNameButton.title = @"No Host Selected";
[self.collectionView reloadData];
@ -339,7 +336,7 @@ static NSMutableSet* hostList;
_streamConfig.appID = app.id;
DataManager* dataMan = [[DataManager alloc] init];
Settings* streamSettings = [dataMan retrieveSettings];
TemporarySettings* streamSettings = [dataMan getSettings];
_streamConfig.frameRate = [streamSettings.framerate intValue];
_streamConfig.bitRate = [streamSettings.bitrate intValue];
@ -556,14 +553,11 @@ static NSMutableSet* hostList;
// Purge the box art cache
[_boxArtCache removeAllObjects];
// In case the host objects were updated in the background
[[[DataManager alloc] init] saveData];
}
- (void) retrieveSavedHosts {
DataManager* dataMan = [[DataManager alloc] init];
NSArray* hosts = [dataMan retrieveHosts];
NSArray* hosts = [dataMan getHosts];
@synchronized(hostList) {
[hostList addObjectsFromArray:hosts];

View File

@ -7,7 +7,7 @@
//
#import "SettingsViewController.h"
#import "Settings.h"
#import "TemporarySettings.h"
#import "DataManager.h"
#define BITRATE_INTERVAL 500 // in kbps
@ -22,7 +22,7 @@ static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
[super viewDidLoad];
DataManager* dataMan = [[DataManager alloc] init];
Settings* currentSettings = [dataMan retrieveSettings];
TemporarySettings* currentSettings = [dataMan getSettings];
// Bitrate is persisted in kbps
_bitrate = [currentSettings.bitrate integerValue];

View File

@ -10,6 +10,7 @@
9832D1361BBCD5C50036EF48 /* TemporaryApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 9832D1351BBCD5C50036EF48 /* TemporaryApp.m */; };
987140041B04542F00AB57D5 /* libmoonlight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FB1E43101AE8B0F200AFF679 /* libmoonlight-common.a */; };
98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */; };
98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */; };
9E5D600B1A5A5A3900689918 /* Apache License.txt in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D5FF81A5A5A3900689918 /* Apache License.txt */; };
9E5D600C1A5A5A3900689918 /* Roboto-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D5FF91A5A5A3900689918 /* Roboto-Black.ttf */; };
9E5D600E1A5A5A3900689918 /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D5FFB1A5A5A3900689918 /* Roboto-Bold.ttf */; };
@ -101,6 +102,8 @@
98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "moonlight-common.xcodeproj"; path = "limelight-common-c/moonlight-common.xcodeproj"; sourceTree = "<group>"; };
98D5856B1C0EA79600F6CC00 /* TemporaryHost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporaryHost.h; path = Database/TemporaryHost.h; sourceTree = "<group>"; };
98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TemporaryHost.m; path = Database/TemporaryHost.m; sourceTree = "<group>"; };
98D5856E1C0ED0E800F6CC00 /* TemporarySettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporarySettings.h; path = Database/TemporarySettings.h; sourceTree = "<group>"; };
98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TemporarySettings.m; path = Database/TemporarySettings.m; sourceTree = "<group>"; };
9E5D5FF81A5A5A3900689918 /* Apache License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Apache License.txt"; sourceTree = "<group>"; };
9E5D5FF91A5A5A3900689918 /* Roboto-Black.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Black.ttf"; sourceTree = "<group>"; };
9E5D5FFB1A5A5A3900689918 /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Bold.ttf"; sourceTree = "<group>"; };
@ -738,6 +741,8 @@
9832D1351BBCD5C50036EF48 /* TemporaryApp.m */,
98D5856B1C0EA79600F6CC00 /* TemporaryHost.h */,
98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */,
98D5856E1C0ED0E800F6CC00 /* TemporarySettings.h */,
98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */,
);
name = Database;
sourceTree = "<group>";
@ -866,6 +871,7 @@
FB1D599A1BBCCD7E00F482CA /* AppCollectionView.m in Sources */,
FB89463619F646E200339C8A /* StreamFrameViewController.m in Sources */,
9832D1361BBCD5C50036EF48 /* TemporaryApp.m in Sources */,
98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */,
FB89462819F646E200339C8A /* CryptoManager.m in Sources */,
FB89462E19F646E200339C8A /* PairManager.m in Sources */,
FB9AFD371A7E02DB00872C98 /* HttpRequest.m in Sources */,