| 1 | /* |
|---|
| 2 | * SapphireMetaDataSupport.m |
|---|
| 3 | * Sapphire |
|---|
| 4 | * |
|---|
| 5 | * Created by Graham Booker on Apr. 16, 2008. |
|---|
| 6 | * Copyright 2008 Sapphire Development Team and/or www.nanopi.net |
|---|
| 7 | * All rights reserved. |
|---|
| 8 | * |
|---|
| 9 | * This program is free software; you can redistribute it and/or modify it under the terms of the GNU |
|---|
| 10 | * General Public License as published by the Free Software Foundation; either version 3 of the License, |
|---|
| 11 | * or (at your option) any later version. |
|---|
| 12 | * |
|---|
| 13 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
|---|
| 14 | * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
|---|
| 15 | * Public License for more details. |
|---|
| 16 | * |
|---|
| 17 | * You should have received a copy of the GNU General Public License along with this program; if not, |
|---|
| 18 | * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|---|
| 19 | */ |
|---|
| 20 | |
|---|
| 21 | #import "SapphireMetaDataSupport.h" |
|---|
| 22 | #import "SapphireDirectoryMetaData.h" |
|---|
| 23 | #import "SapphireFileMetaData.h" |
|---|
| 24 | #import "SapphireJoinedFile.h" |
|---|
| 25 | #import "SapphireCollectionDirectory.h" |
|---|
| 26 | #import "SapphireMovie.h" |
|---|
| 27 | #import "SapphireCast.h" |
|---|
| 28 | #import "SapphireMovieTranslation.h" |
|---|
| 29 | #import "SapphireMoviePoster.h" |
|---|
| 30 | #import "SapphireTVTranslation.h" |
|---|
| 31 | #import "SapphireTVShow.h" |
|---|
| 32 | #import "SapphireMetaDataUpgrading.h" |
|---|
| 33 | |
|---|
| 34 | #define META_VERSION_KEY @"Version" |
|---|
| 35 | |
|---|
| 36 | /* Movie Translations */ |
|---|
| 37 | #define MOVIE_TRAN_VERSION_KEY @"Version" |
|---|
| 38 | #define MOVIE_TRAN_CURRENT_VERSION 2 |
|---|
| 39 | /* Translation Keys */ |
|---|
| 40 | #define MOVIE_TRAN_TRANSLATIONS_KEY @"Translations" |
|---|
| 41 | #define MOVIE_TRAN_IMDB_LINK_KEY @"IMDB Link" |
|---|
| 42 | #define MOVIE_TRAN_IMP_LINK_KEY @"IMP Link" |
|---|
| 43 | #define MOVIE_TRAN_IMP_POSTERS_KEY @"IMP Posters" |
|---|
| 44 | #define MOVIE_TRAN_SELECTED_POSTER_KEY @"Selected Poster" |
|---|
| 45 | #define MOVIE_TRAN_AUTO_SELECT_POSTER_KEY @"Default Poster" |
|---|
| 46 | |
|---|
| 47 | static NSSet *coverArtExtentions = nil; |
|---|
| 48 | |
|---|
| 49 | NSString *searchCoverArtExtForPath(NSString *path) |
|---|
| 50 | { |
|---|
| 51 | NSFileManager *fm = [NSFileManager defaultManager]; |
|---|
| 52 | NSString *directory = [path stringByDeletingLastPathComponent]; |
|---|
| 53 | NSArray *files = [fm directoryContentsAtPath:directory]; |
|---|
| 54 | NSString *lastComp = [path lastPathComponent]; |
|---|
| 55 | /*Search all files*/ |
|---|
| 56 | NSEnumerator *fileEnum = [files objectEnumerator]; |
|---|
| 57 | NSString *file = nil; |
|---|
| 58 | while((file = [fileEnum nextObject]) != nil) |
|---|
| 59 | { |
|---|
| 60 | NSString *ext = [file pathExtension]; |
|---|
| 61 | if([ext length] && |
|---|
| 62 | [coverArtExtentions containsObject:ext] && |
|---|
| 63 | [lastComp caseInsensitiveCompare:[file stringByDeletingPathExtension]] == NSOrderedSame) |
|---|
| 64 | return [directory stringByAppendingPathComponent:file]; |
|---|
| 65 | } |
|---|
| 66 | /*Didn't find one*/ |
|---|
| 67 | return nil; |
|---|
| 68 | } |
|---|
| 69 | |
|---|
| 70 | @implementation SapphireMetaDataSupport |
|---|
| 71 | |
|---|
| 72 | + (void)load |
|---|
| 73 | { |
|---|
| 74 | coverArtExtentions = [[NSSet alloc] initWithObjects: |
|---|
| 75 | @"jpg", |
|---|
| 76 | @"jpeg", |
|---|
| 77 | @"tif", |
|---|
| 78 | @"tiff", |
|---|
| 79 | @"png", |
|---|
| 80 | @"gif", |
|---|
| 81 | nil]; |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | + (SapphireMetaDataSupport *)sharedInstance |
|---|
| 85 | { |
|---|
| 86 | static SapphireMetaDataSupport *shared = nil; |
|---|
| 87 | |
|---|
| 88 | if(shared == nil) |
|---|
| 89 | shared = [[SapphireMetaDataSupport alloc] init]; |
|---|
| 90 | |
|---|
| 91 | return shared; |
|---|
| 92 | } |
|---|
| 93 | |
|---|
| 94 | - (void) dealloc |
|---|
| 95 | { |
|---|
| 96 | [writeTimer invalidate]; |
|---|
| 97 | writeTimer = nil; |
|---|
| 98 | [super dealloc]; |
|---|
| 99 | } |
|---|
| 100 | |
|---|
| 101 | |
|---|
| 102 | - (void)realWriteMetaData:(NSTimer *)timer |
|---|
| 103 | { |
|---|
| 104 | NSManagedObjectContext *context = nil; |
|---|
| 105 | if([timer isKindOfClass:[NSManagedObjectContext class]]) |
|---|
| 106 | context = (NSManagedObjectContext *)timer; |
|---|
| 107 | else |
|---|
| 108 | context = [timer userInfo]; |
|---|
| 109 | |
|---|
| 110 | [writeTimer invalidate]; |
|---|
| 111 | writeTimer = nil; |
|---|
| 112 | NSError *error = nil; |
|---|
| 113 | BOOL success = NO; |
|---|
| 114 | @try { |
|---|
| 115 | success = [context save:&error]; |
|---|
| 116 | } |
|---|
| 117 | @catch (NSException * e) { |
|---|
| 118 | NSLog(@"Could not save due to exception \"%@\" with reason\"%@\"", [e name], [e reason]); |
|---|
| 119 | } |
|---|
| 120 | if(error != nil) |
|---|
| 121 | NSLog(@"Save error \"%@\"", error); |
|---|
| 122 | if(success == NO) |
|---|
| 123 | { |
|---|
| 124 | interval *= 2; |
|---|
| 125 | [writeTimer invalidate]; |
|---|
| 126 | writeTimer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(realWriteMetaData:) userInfo:context repeats:NO]; |
|---|
| 127 | } |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | - (BOOL)save:(NSManagedObjectContext *)context; |
|---|
| 131 | { |
|---|
| 132 | if(writeTimer == nil) |
|---|
| 133 | { |
|---|
| 134 | interval = 1; |
|---|
| 135 | [self realWriteMetaData:(NSTimer *)context]; |
|---|
| 136 | return (writeTimer == nil); |
|---|
| 137 | } |
|---|
| 138 | else |
|---|
| 139 | return YES; |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | + (BOOL)save:(NSManagedObjectContext *)context |
|---|
| 143 | { |
|---|
| 144 | if(context == nil) |
|---|
| 145 | return NO; |
|---|
| 146 | |
|---|
| 147 | return [[SapphireMetaDataSupport sharedInstance] save:context]; |
|---|
| 148 | } |
|---|
| 149 | |
|---|
| 150 | + (void)importPlist:(NSString *)configDir intoContext:(NSManagedObjectContext *)context withDisplay:(SapphireMetaDataUpgrading *)display |
|---|
| 151 | { |
|---|
| 152 | NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:[configDir stringByAppendingPathComponent:@"metaData.plist"]]; |
|---|
| 153 | NSMutableDictionary *defer = [NSMutableDictionary dictionaryWithObjectsAndKeys: |
|---|
| 154 | [NSMutableDictionary dictionary], @"Join", |
|---|
| 155 | nil]; |
|---|
| 156 | int version = [[dict objectForKey:META_VERSION_KEY] intValue]; |
|---|
| 157 | SapphireDirectoryMetaData *newDir = nil; |
|---|
| 158 | if(version > 2) |
|---|
| 159 | { |
|---|
| 160 | NSDictionary *slash = [dict objectForKey:@"/"]; |
|---|
| 161 | newDir = [SapphireDirectoryMetaData createDirectoryWithPath:@"/" parent:nil inContext:context]; |
|---|
| 162 | [newDir insertDictionary:slash withDefer:defer andDisplay:display]; |
|---|
| 163 | } |
|---|
| 164 | else |
|---|
| 165 | { |
|---|
| 166 | newDir = [SapphireDirectoryMetaData createDirectoryWithPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Movies"] parent:nil inContext:context]; |
|---|
| 167 | [newDir insertDictionary:dict withDefer:defer andDisplay:display]; |
|---|
| 168 | } |
|---|
| 169 | [display setCurrentFile:BRLocalizedString(@"Upgrading Joined Files", @"")]; |
|---|
| 170 | NSDictionary *joinDict = [defer objectForKey:@"Join"]; |
|---|
| 171 | if(joinDict != nil) |
|---|
| 172 | { |
|---|
| 173 | NSEnumerator *joinEunm = [joinDict keyEnumerator]; |
|---|
| 174 | NSString *joinedPath; |
|---|
| 175 | while((joinedPath = [joinEunm nextObject]) != nil) |
|---|
| 176 | { |
|---|
| 177 | SapphireJoinedFile *joinedFile = [SapphireJoinedFile joinedFileForPath:joinedPath inContext:context]; |
|---|
| 178 | NSArray *joinArray = [joinDict objectForKey:joinedPath]; |
|---|
| 179 | NSEnumerator *joinedEnum = [joinArray objectEnumerator]; |
|---|
| 180 | SapphireFileMetaData *joinFile; |
|---|
| 181 | while((joinFile = [joinedEnum nextObject]) != nil) |
|---|
| 182 | joinFile.joinedToFile = joinedFile; |
|---|
| 183 | } |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | [display setCurrentFile:BRLocalizedString(@"Upgrading Collection Prefs", @"")]; |
|---|
| 187 | NSDictionary *options = [dict objectForKey:@"Options"]; |
|---|
| 188 | NSMutableSet *collections = [NSMutableSet set]; |
|---|
| 189 | NSArray *custom = [options objectForKey:@"Directories"]; |
|---|
| 190 | if([custom count]) |
|---|
| 191 | [collections unionSet:[NSSet setWithArray:custom]]; |
|---|
| 192 | NSDictionary *hidden = [options objectForKey:@"Hide"]; |
|---|
| 193 | NSArray *keyArray = [hidden allKeys]; |
|---|
| 194 | if([keyArray count]) |
|---|
| 195 | [collections unionSet:[NSSet setWithArray:keyArray]]; |
|---|
| 196 | NSDictionary *skipped = [options objectForKey:@"Skip"]; |
|---|
| 197 | keyArray = [skipped allKeys]; |
|---|
| 198 | if([keyArray count]) |
|---|
| 199 | [collections unionSet:[NSSet setWithArray:keyArray]]; |
|---|
| 200 | |
|---|
| 201 | NSEnumerator *collectionEnum = [collections objectEnumerator]; |
|---|
| 202 | NSString *collectionPath; |
|---|
| 203 | while((collectionPath = [collectionEnum nextObject]) != nil) |
|---|
| 204 | { |
|---|
| 205 | [SapphireCollectionDirectory collectionAtPath:collectionPath |
|---|
| 206 | mount:NO |
|---|
| 207 | skip:[[skipped objectForKey:collectionPath] boolValue] |
|---|
| 208 | hidden:[[hidden objectForKey:collectionPath] boolValue] |
|---|
| 209 | manual:[custom containsObject:collectionPath] |
|---|
| 210 | inContext:context]; |
|---|
| 211 | } |
|---|
| 212 | //Set the mount values for all |
|---|
| 213 | [SapphireCollectionDirectory availableCollectionDirectoriesInContext:context]; |
|---|
| 214 | |
|---|
| 215 | [display setCurrentFile:BRLocalizedString(@"Upgrading Movie Translations", @"")]; |
|---|
| 216 | NSDictionary *movieTranslations = [NSDictionary dictionaryWithContentsOfFile:[configDir stringByAppendingPathComponent:@"movieData.plist"]]; |
|---|
| 217 | NSDictionary *translations = [movieTranslations objectForKey:MOVIE_TRAN_TRANSLATIONS_KEY]; |
|---|
| 218 | NSEnumerator *movieEnum = [translations keyEnumerator]; |
|---|
| 219 | NSString *movie = nil; |
|---|
| 220 | while((movie = [movieEnum nextObject]) != nil) |
|---|
| 221 | { |
|---|
| 222 | NSDictionary *movieDict = [translations objectForKey:movie]; |
|---|
| 223 | SapphireMovieTranslation *trans = [SapphireMovieTranslation createMovieTranslationWithName:movie inContext:context]; |
|---|
| 224 | trans.IMPLink = [movieDict objectForKey:MOVIE_TRAN_IMP_LINK_KEY]; |
|---|
| 225 | NSString *IMDBLink = [movieDict objectForKey:MOVIE_TRAN_IMDB_LINK_KEY]; |
|---|
| 226 | trans.IMDBLink = IMDBLink; |
|---|
| 227 | |
|---|
| 228 | int imdbNumber = [SapphireMovie imdbNumberFromString:IMDBLink]; |
|---|
| 229 | if(imdbNumber != 0) |
|---|
| 230 | { |
|---|
| 231 | SapphireMovie *thisMovie = [SapphireMovie movieWithIMDB:imdbNumber inContext:context]; |
|---|
| 232 | trans.movie = thisMovie; |
|---|
| 233 | } |
|---|
| 234 | |
|---|
| 235 | NSArray *posters = [movieDict objectForKey:MOVIE_TRAN_IMP_POSTERS_KEY]; |
|---|
| 236 | NSSet *dupCheck = [NSSet setWithArray:posters]; |
|---|
| 237 | posters = [dupCheck allObjects]; |
|---|
| 238 | |
|---|
| 239 | NSString *selectedPoster = [movieDict objectForKey:MOVIE_TRAN_SELECTED_POSTER_KEY]; |
|---|
| 240 | int i, count = [posters count]; |
|---|
| 241 | for(i=0; i<count; i++) |
|---|
| 242 | { |
|---|
| 243 | NSString *posterUrl = [posters objectAtIndex:i]; |
|---|
| 244 | if([posterUrl isEqualToString:selectedPoster]) |
|---|
| 245 | trans.selectedPosterIndexValue = i; |
|---|
| 246 | |
|---|
| 247 | [SapphireMoviePoster createPosterWithLink:posterUrl index:i translation:trans inContext:context]; |
|---|
| 248 | } |
|---|
| 249 | } |
|---|
| 250 | |
|---|
| 251 | [display setCurrentFile:BRLocalizedString(@"Upgrading TV Translations", @"")]; |
|---|
| 252 | NSDictionary *tvTranslations = [NSDictionary dictionaryWithContentsOfFile:[configDir stringByAppendingPathComponent:@"tvdata.plist"]]; |
|---|
| 253 | translations = [tvTranslations objectForKey:@"Translations"]; |
|---|
| 254 | NSEnumerator *tvEnum = [translations keyEnumerator]; |
|---|
| 255 | NSString *tvShow = nil; |
|---|
| 256 | while((tvShow = [tvEnum nextObject]) != nil) |
|---|
| 257 | { |
|---|
| 258 | NSString *showPath = [translations objectForKey:tvShow]; |
|---|
| 259 | SapphireTVTranslation *trans = [SapphireTVTranslation createTVTranslationForName:tvShow withPath:showPath inContext:context]; |
|---|
| 260 | SapphireTVShow *show = [SapphireTVShow showWithPath:showPath inContext:context]; |
|---|
| 261 | trans.tvShow = show; |
|---|
| 262 | } |
|---|
| 263 | |
|---|
| 264 | NSError *error = nil; |
|---|
| 265 | NSManagedObject *obj; |
|---|
| 266 | NSEnumerator *objEnum = [[context registeredObjects] objectEnumerator]; |
|---|
| 267 | while((obj = [objEnum nextObject]) != nil) |
|---|
| 268 | { |
|---|
| 269 | if(![obj validateForUpdate:&error]) |
|---|
| 270 | NSLog(@"%@", error); |
|---|
| 271 | } |
|---|
| 272 | [display setCurrentFile:BRLocalizedString(@"Upgrading Complete; Press Menu to Go Back", @"")]; |
|---|
| 273 | } |
|---|
| 274 | |
|---|
| 275 | + (NSString *)collectionArtPath |
|---|
| 276 | { |
|---|
| 277 | static NSString *path = nil; |
|---|
| 278 | if(path == nil) |
|---|
| 279 | path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/Collection Art"] retain]; |
|---|
| 280 | return path; |
|---|
| 281 | } |
|---|
| 282 | |
|---|
| 283 | @end |
|---|