diff --git a/Limelight/Database/DataManager.h b/Limelight/Database/DataManager.h
index 1ff40570..611df00d 100644
--- a/Limelight/Database/DataManager.h
+++ b/Limelight/Database/DataManager.h
@@ -28,7 +28,6 @@
- (NSArray*) getHosts;
- (void) updateHost:(TemporaryHost*)host;
- (void) updateAppsForExistingHost:(TemporaryHost *)host;
-- (void) updateIconForExistingApp:(TemporaryApp*)app;
- (void) removeHost:(TemporaryHost*)host;
- (void) removeApp:(TemporaryApp*)app;
diff --git a/Limelight/Database/DataManager.m b/Limelight/Database/DataManager.m
index 374d6738..22bb1296 100644
--- a/Limelight/Database/DataManager.m
+++ b/Limelight/Database/DataManager.m
@@ -128,20 +128,6 @@
}];
}
-- (void) updateIconForExistingApp:(TemporaryApp*)app {
- [_managedObjectContext performBlockAndWait:^{
- App* parentApp = [self getAppForTemporaryApp:app withAppRecords:[self fetchRecords:@"App"]];
- if (parentApp == nil) {
- // The app must exist to be updated
- return;
- }
-
- parentApp.image = app.image;
-
- [self saveData];
- }];
-}
-
- (TemporarySettings*) getSettings {
__block TemporarySettings *tempSettings;
diff --git a/Limelight/Database/TemporaryApp.h b/Limelight/Database/TemporaryApp.h
index 93056552..b1c4d2d6 100644
--- a/Limelight/Database/TemporaryApp.h
+++ b/Limelight/Database/TemporaryApp.h
@@ -12,7 +12,6 @@
@interface TemporaryApp : NSObject
@property (nullable, nonatomic, retain) NSString *id;
-@property (nullable, nonatomic, retain) NSData *image;
@property (nullable, nonatomic, retain) NSString *name;
@property (nonatomic) BOOL hdrSupported;
@property (nullable, nonatomic, retain) TemporaryHost *host;
diff --git a/Limelight/Database/TemporaryApp.m b/Limelight/Database/TemporaryApp.m
index 85a43725..8d373209 100644
--- a/Limelight/Database/TemporaryApp.m
+++ b/Limelight/Database/TemporaryApp.m
@@ -14,7 +14,6 @@
self = [self init];
self.id = app.id;
- self.image = app.image;
self.name = app.name;
self.hdrSupported = app.hdrSupported;
self.host = tempHost;
diff --git a/Limelight/Limelight.xcdatamodeld/.xccurrentversion b/Limelight/Limelight.xcdatamodeld/.xccurrentversion
index d880a371..3bc8a00c 100644
--- a/Limelight/Limelight.xcdatamodeld/.xccurrentversion
+++ b/Limelight/Limelight.xcdatamodeld/.xccurrentversion
@@ -3,6 +3,6 @@
_XCCurrentVersionName
- Moonlight v1.1.xcdatamodel
+ Moonlight v1.2.xcdatamodel
diff --git a/Limelight/Limelight.xcdatamodeld/Moonlight v1.2.xcdatamodel/contents b/Limelight/Limelight.xcdatamodeld/Moonlight v1.2.xcdatamodel/contents
new file mode 100644
index 00000000..0d3feba0
--- /dev/null
+++ b/Limelight/Limelight.xcdatamodeld/Moonlight v1.2.xcdatamodel/contents
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Limelight/Network/AppAssetManager.h b/Limelight/Network/AppAssetManager.h
index 1d05ce98..d2020729 100644
--- a/Limelight/Network/AppAssetManager.h
+++ b/Limelight/Network/AppAssetManager.h
@@ -21,5 +21,6 @@
- (id) initWithCallback:(id)callback;
- (void) retrieveAssetsFromHost:(TemporaryHost*)host;
- (void) stopRetrieving;
++ (NSString*) boxArtPathForApp:(TemporaryApp*)app;
@end
diff --git a/Limelight/Network/AppAssetManager.m b/Limelight/Network/AppAssetManager.m
index f8a8f5df..4a6480df 100644
--- a/Limelight/Network/AppAssetManager.m
+++ b/Limelight/Network/AppAssetManager.m
@@ -19,6 +19,22 @@
static const int MAX_REQUEST_COUNT = 4;
++ (NSString*) boxArtPathForApp:(TemporaryApp*)app {
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
+ NSString *filePath = [paths objectAtIndex:0];
+
+ // Keep app assets separate by host UUID
+ filePath = [filePath stringByAppendingPathComponent:app.host.uuid];
+
+ // Use the app ID as the file name
+ filePath = [filePath stringByAppendingPathComponent:app.id];
+
+ // Add a png extension
+ filePath = [filePath stringByAppendingPathExtension:@"png"];
+
+ return filePath;
+}
+
- (id) initWithCallback:(id)callback {
self = [super init];
_callback = callback;
@@ -30,7 +46,7 @@ static const int MAX_REQUEST_COUNT = 4;
- (void) retrieveAssetsFromHost:(TemporaryHost*)host {
for (TemporaryApp* app in host.appList) {
- if (app.image == nil) {
+ if (![[NSFileManager defaultManager] fileExistsAtPath:[AppAssetManager boxArtPathForApp:app]]) {
AppAssetRetriever* retriever = [[AppAssetRetriever alloc] init];
retriever.app = app;
retriever.host = host;
diff --git a/Limelight/Network/AppAssetRetriever.m b/Limelight/Network/AppAssetRetriever.m
index 43d3aeb0..30dce859 100644
--- a/Limelight/Network/AppAssetRetriever.m
+++ b/Limelight/Network/AppAssetRetriever.m
@@ -18,25 +18,24 @@ static const double RETRY_DELAY = 2; // seconds
static const int MAX_ATTEMPTS = 5;
- (void) main {
-
- OSImage* appImage = nil;
-
int attempts = 0;
- while (![self isCancelled] && appImage == nil && attempts++ < MAX_ATTEMPTS) {
-
+ while (![self isCancelled] && attempts++ < MAX_ATTEMPTS) {
HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.activeAddress uniqueId:[IdManager getUniqueId] deviceName:deviceName cert:[CryptoManager readCertFromFile]];
AppAssetResponse* appAssetResp = [[AppAssetResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appAssetResp withUrlRequest:[hMan newAppAssetRequestWithAppId:self.app.id]]];
#if TARGET_OS_IPHONE
- appImage = [UIImage imageWithData:appAssetResp.data];
- self.app.image = UIImagePNGRepresentation(appImage);
+ if (appAssetResp.data != nil) {
+ NSString* boxArtPath = [AppAssetManager boxArtPathForApp:self.app];
+ [[NSFileManager defaultManager] createDirectoryAtPath:[boxArtPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
+ [appAssetResp.data writeToFile:boxArtPath atomically:NO];
+ break;
+ }
#else
#endif
-
- if (![self isCancelled] && appImage == nil) {
+ if (![self isCancelled]) {
[NSThread sleepForTimeInterval:RETRY_DELAY];
}
}
diff --git a/Limelight/UIAppView.m b/Limelight/UIAppView.m
index f519959c..03094eb5 100644
--- a/Limelight/UIAppView.m
+++ b/Limelight/UIAppView.m
@@ -7,6 +7,7 @@
//
#import "UIAppView.h"
+#import "AppAssetManager.h"
@implementation UIAppView {
TemporaryApp* _app;
@@ -74,19 +75,20 @@ static UIImage* noImage;
[_appOverlay setCenter:CGPointMake(self.frame.size.width/2, self.frame.size.height/6)];
}
- // TODO: Improve no-app image detection
BOOL noAppImage = false;
- if (_app.image != nil) {
- // Load the decoded image from the cache
- UIImage* appImage = [_artCache objectForKey:_app];
- if (appImage == nil) {
- // Not cached; we have to decode this now
- appImage = [UIImage imageWithData:_app.image];
+ // First check the memory cache
+ UIImage* appImage = [_artCache objectForKey:_app];
+ if (appImage == nil) {
+ // Next try to load from the on disk cache
+ appImage = [UIImage imageWithContentsOfFile:[AppAssetManager boxArtPathForApp:_app]];
+ if (appImage != nil) {
[_artCache setObject:appImage forKey:_app];
}
-
+ }
+ if (appImage != nil) {
// This size of image might be blank image received from GameStream.
+ // TODO: Improve no-app image detection
if (!(appImage.size.width == 130.f && appImage.size.height == 180.f) && // GFE 2.0
!(appImage.size.width == 628.f && appImage.size.height == 888.f)) { // GFE 3.0
_appButton.frame = CGRectMake(0, 0, appImage.size.width / 2, appImage.size.height / 2);
diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m
index 572736ba..2b2ae896 100644
--- a/Limelight/ViewControllers/MainFrameViewController.m
+++ b/Limelight/ViewControllers/MainFrameViewController.m
@@ -263,9 +263,6 @@ static NSMutableSet* hostList;
// on the main thread
[self updateBoxArtCacheForApp:app];
- DataManager* dataManager = [[DataManager alloc] init];
- [dataManager updateIconForExistingApp: app];
-
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
});
@@ -926,7 +923,13 @@ static NSMutableSet* hostList;
+ (UIImage*) loadBoxArtForCaching:(TemporaryApp*)app {
UIImage* boxArt;
- CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)app.image, NULL);
+ NSData* imageData = [NSData dataWithContentsOfFile:[AppAssetManager boxArtPathForApp:app]];
+ if (imageData == nil) {
+ // No box art on disk
+ return nil;
+ }
+
+ CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, nil);
size_t width = CGImageGetWidth(cgImage);
@@ -953,11 +956,12 @@ static NSMutableSet* hostList;
}
- (void) updateBoxArtCacheForApp:(TemporaryApp*)app {
- if (app.image == nil) {
- [_boxArtCache removeObjectForKey:app];
- }
- else if ([_boxArtCache objectForKey:app] == nil) {
- [_boxArtCache setObject:[MainFrameViewController loadBoxArtForCaching:app] forKey:app];
+ if ([_boxArtCache objectForKey:app] == nil) {
+ UIImage* image = [MainFrameViewController loadBoxArtForCaching:app];
+ if (image != nil) {
+ // Add the image to our cache if it was present
+ [_boxArtCache setObject:image forKey:app];
+ }
}
}
diff --git a/Moonlight.xcodeproj/project.pbxproj b/Moonlight.xcodeproj/project.pbxproj
index a5fcedbc..dc484dd6 100644
--- a/Moonlight.xcodeproj/project.pbxproj
+++ b/Moonlight.xcodeproj/project.pbxproj
@@ -164,6 +164,7 @@
9832D1341BBCD5C50036EF48 /* TemporaryApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporaryApp.h; path = Database/TemporaryApp.h; sourceTree = ""; };
9832D1351BBCD5C50036EF48 /* TemporaryApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TemporaryApp.m; path = Database/TemporaryApp.m; sourceTree = ""; };
9865DC3B2132922E0005B9B9 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.4.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; };
+ 986CCE6C2133E45300168291 /* Moonlight v1.2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.2.xcdatamodel"; sourceTree = ""; };
98878AE0206A226D00586E90 /* OSPortabilityDefs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSPortabilityDefs.h; sourceTree = ""; };
9890CF6A203B7EE1006C4B06 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = usr/lib/libxml2.tbd; sourceTree = SDKROOT; };
98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "moonlight-common.xcodeproj"; path = "moonlight-common/moonlight-common.xcodeproj"; sourceTree = ""; };
@@ -1499,6 +1500,7 @@
FB290D0519B2C406004C83CF /* Limelight.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
+ 986CCE6C2133E45300168291 /* Moonlight v1.2.xcdatamodel */,
98132E8C20BC9A62007A053F /* Moonlight v1.1.xcdatamodel */,
FB53E1441BE5DCBC00CD6ECE /* Moonlight v1.0-2.xcdatamodel */,
FBB460391B50ACE400F3099C /* Moonlight v1.0.xcdatamodel */,
@@ -1506,7 +1508,7 @@
FB4678F21A51BDCB00377732 /* Limelight 0.3.0.xcdatamodel */,
FB290D0619B2C406004C83CF /* Limelight.xcdatamodel */,
);
- currentVersion = 98132E8C20BC9A62007A053F /* Moonlight v1.1.xcdatamodel */;
+ currentVersion = 986CCE6C2133E45300168291 /* Moonlight v1.2.xcdatamodel */;
path = Limelight.xcdatamodeld;
sourceTree = "";
versionGroupType = wrapper.xcdatamodel;