| 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 "SapphireMovieCategories.h" |
|---|
| 29 | #import "SapphireMovieTranslation.h" |
|---|
| 30 | #import "SapphireMoviePoster.h" |
|---|
| 31 | #import "SapphireTVTranslation.h" |
|---|
| 32 | #import "SapphireTVShow.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 isEqualToString:[file stringByDeletingPathExtension]]) |
|---|
| 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)realWriteMetaData:(NSTimer *)timer |
|---|
| 95 | { |
|---|
| 96 | writeTimer = nil; |
|---|
| 97 | NSManagedObjectContext *context = nil; |
|---|
| 98 | if([timer isKindOfClass:[NSManagedObjectContext class]]) |
|---|
| 99 | context = (NSManagedObjectContext *)timer; |
|---|
| 100 | else |
|---|
| 101 | context = [timer userInfo]; |
|---|
| 102 | NSError *error = nil; |
|---|
| 103 | [context save:&error]; |
|---|
| 104 | } |
|---|
| 105 | |
|---|
| 106 | - (void)save:(NSManagedObjectContext *)context; |
|---|
| 107 | { |
|---|
| 108 | /* [writeTimer invalidate]; |
|---|
| 109 | writeTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(realWriteMetaData:) userInfo:context repeats:NO];*/ |
|---|
| 110 | [self realWriteMetaData:(NSTimer *)context]; |
|---|
| 111 | } |
|---|
| 112 | |
|---|
| 113 | + (void)save:(NSManagedObjectContext *)context |
|---|
| 114 | { |
|---|
| 115 | if(context == nil) |
|---|
| 116 | return; |
|---|
| 117 | |
|---|
| 118 | [[SapphireMetaDataSupport sharedInstance] save:context]; |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | + (void)importPlist:(NSString *)configDir intoContext:(NSManagedObjectContext *)context |
|---|
| 122 | { |
|---|
| 123 | NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:[configDir stringByAppendingPathComponent:@"metaData.plist"]]; |
|---|
| 124 | NSMutableDictionary *defer = [NSMutableDictionary dictionaryWithObjectsAndKeys: |
|---|
| 125 | [NSMutableDictionary dictionary], @"defer", |
|---|
| 126 | nil]; |
|---|
| 127 | int version = [[dict objectForKey:META_VERSION_KEY] intValue]; |
|---|
| 128 | SapphireDirectoryMetaData *newDir = nil; |
|---|
| 129 | if(version > 2) |
|---|
| 130 | { |
|---|
| 131 | NSDictionary *slash = [dict objectForKey:@"/"]; |
|---|
| 132 | newDir = [SapphireDirectoryMetaData createDirectoryWithPath:@"/" parent:nil inContext:context]; |
|---|
| 133 | [newDir insertDictionary:slash withDefer:defer]; |
|---|
| 134 | } |
|---|
| 135 | else |
|---|
| 136 | { |
|---|
| 137 | newDir = [SapphireDirectoryMetaData createDirectoryWithPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Movies"] parent:nil inContext:context]; |
|---|
| 138 | [newDir insertDictionary:dict withDefer:defer]; |
|---|
| 139 | } |
|---|
| 140 | NSDictionary *joinDict = [defer objectForKey:@"Join"]; |
|---|
| 141 | if(joinDict != nil) |
|---|
| 142 | { |
|---|
| 143 | NSEnumerator *joinEunm = [joinDict keyEnumerator]; |
|---|
| 144 | NSString *joinedPath; |
|---|
| 145 | while((joinedPath = [joinEunm nextObject]) != nil) |
|---|
| 146 | { |
|---|
| 147 | SapphireJoinedFile *joinedFile = [SapphireJoinedFile joinedFileForPath:joinedPath inContext:context]; |
|---|
| 148 | NSArray *joinArray = [joinDict objectForKey:joinedPath]; |
|---|
| 149 | NSEnumerator *joinedEnum = [joinArray objectEnumerator]; |
|---|
| 150 | SapphireFileMetaData *joinFile; |
|---|
| 151 | while((joinFile = [joinedEnum nextObject]) != nil) |
|---|
| 152 | joinFile.joinedToFile = joinedFile; |
|---|
| 153 | } |
|---|
| 154 | } |
|---|
| 155 | |
|---|
| 156 | NSDictionary *options = [dict objectForKey:@"Options"]; |
|---|
| 157 | NSMutableSet *collections = [NSMutableSet set]; |
|---|
| 158 | NSArray *custom = [options objectForKey:@"Directories"]; |
|---|
| 159 | if([custom count]) |
|---|
| 160 | [collections unionSet:[NSSet setWithArray:custom]]; |
|---|
| 161 | NSDictionary *hidden = [options objectForKey:@"Hide"]; |
|---|
| 162 | NSArray *keyArray = [hidden allKeys]; |
|---|
| 163 | if([keyArray count]) |
|---|
| 164 | [collections unionSet:[NSSet setWithArray:keyArray]]; |
|---|
| 165 | NSDictionary *skipped = [options objectForKey:@"Skip"]; |
|---|
| 166 | keyArray = [skipped allKeys]; |
|---|
| 167 | if([keyArray count]) |
|---|
| 168 | [collections unionSet:[NSSet setWithArray:keyArray]]; |
|---|
| 169 | |
|---|
| 170 | NSEnumerator *collectionEnum = [collections objectEnumerator]; |
|---|
| 171 | NSString *collectionPath; |
|---|
| 172 | while((collectionPath = [collectionEnum nextObject]) != nil) |
|---|
| 173 | { |
|---|
| 174 | [SapphireCollectionDirectory collectionAtPath:collectionPath mount:([custom containsObject:collectionPath] == nil) skip:[[skipped objectForKey:collectionPath] boolValue] hidden:[[hidden objectForKey:collectionPath] boolValue] inContext:context]; |
|---|
| 175 | } |
|---|
| 176 | |
|---|
| 177 | // NSArray *mountedCollections = [SapphireCollectionDirectory availableCollectionDirectoriesInContext:context]; |
|---|
| 178 | |
|---|
| 179 | NSDictionary *movieTranslations = [NSDictionary dictionaryWithContentsOfFile:[configDir stringByAppendingPathComponent:@"movieData.plist"]]; |
|---|
| 180 | NSDictionary *translations = [movieTranslations objectForKey:MOVIE_TRAN_TRANSLATIONS_KEY]; |
|---|
| 181 | NSEnumerator *movieEnum = [translations keyEnumerator]; |
|---|
| 182 | NSString *movie = nil; |
|---|
| 183 | while((movie = [movieEnum nextObject]) != nil) |
|---|
| 184 | { |
|---|
| 185 | NSDictionary *movieDict = [translations objectForKey:movie]; |
|---|
| 186 | SapphireMovieTranslation *trans = [SapphireMovieTranslation createMovieTranslationWithName:movie inContext:context]; |
|---|
| 187 | trans.IMPLink = [movieDict objectForKey:MOVIE_TRAN_IMP_LINK_KEY]; |
|---|
| 188 | NSString *IMDBLink = [movieDict objectForKey:MOVIE_TRAN_IMDB_LINK_KEY]; |
|---|
| 189 | trans.IMDBLink = IMDBLink; |
|---|
| 190 | |
|---|
| 191 | int imdbNumber = [SapphireMovie imdbNumberFromString:IMDBLink]; |
|---|
| 192 | if(imdbNumber != 0) |
|---|
| 193 | { |
|---|
| 194 | SapphireMovie *thisMovie = [SapphireMovie movieWithIMDB:imdbNumber inContext:context]; |
|---|
| 195 | trans.movie = thisMovie; |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | NSArray *posters = [movieDict objectForKey:MOVIE_TRAN_IMP_POSTERS_KEY]; |
|---|
| 199 | NSSet *dupCheck = [NSSet setWithArray:posters]; |
|---|
| 200 | posters = [dupCheck allObjects]; |
|---|
| 201 | |
|---|
| 202 | NSString *selectedPoster = [movieDict objectForKey:MOVIE_TRAN_SELECTED_POSTER_KEY]; |
|---|
| 203 | int i, count = [posters count]; |
|---|
| 204 | for(i=0; i<count; i++) |
|---|
| 205 | { |
|---|
| 206 | NSString *posterUrl = [posters objectAtIndex:i]; |
|---|
| 207 | if([posterUrl isEqualToString:selectedPoster]) |
|---|
| 208 | trans.selectedPosterIndexValue = i; |
|---|
| 209 | |
|---|
| 210 | [SapphireMoviePoster createPosterWithLink:posterUrl index:i translation:trans inContext:context]; |
|---|
| 211 | } |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | NSDictionary *tvTranslations = [NSDictionary dictionaryWithContentsOfFile:[configDir stringByAppendingPathComponent:@"tvdata.plist"]]; |
|---|
| 215 | translations = [tvTranslations objectForKey:@"Translations"]; |
|---|
| 216 | NSEnumerator *tvEnum = [translations keyEnumerator]; |
|---|
| 217 | NSString *tvShow = nil; |
|---|
| 218 | while((tvShow = [tvEnum nextObject]) != nil) |
|---|
| 219 | { |
|---|
| 220 | NSString *showPath = [translations objectForKey:tvShow]; |
|---|
| 221 | SapphireTVTranslation *trans = [SapphireTVTranslation createTVTranslationForName:tvShow withPath:showPath inContext:context]; |
|---|
| 222 | SapphireTVShow *show = [SapphireTVShow showWithPath:showPath inContext:context]; |
|---|
| 223 | trans.tvShow = show; |
|---|
| 224 | } |
|---|
| 225 | |
|---|
| 226 | NSError *error = nil; |
|---|
| 227 | NSManagedObject *obj; |
|---|
| 228 | NSEnumerator *objEnum = [[context registeredObjects] objectEnumerator]; |
|---|
| 229 | while((obj = [objEnum nextObject]) != nil) |
|---|
| 230 | { |
|---|
| 231 | if(![obj validateForUpdate:&error]) |
|---|
| 232 | NSLog(@"%@", error); |
|---|
| 233 | } |
|---|
| 234 | |
|---|
| 235 | NSLog(@"Sapphire Import Complete"); |
|---|
| 236 | } |
|---|
| 237 | |
|---|
| 238 | + (NSString *)collectionArtPath |
|---|
| 239 | { |
|---|
| 240 | static NSString *path = nil; |
|---|
| 241 | if(path == nil) |
|---|
| 242 | path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/Collection Art"] retain]; |
|---|
| 243 | return path; |
|---|
| 244 | } |
|---|
| 245 | |
|---|
| 246 | @end |
|---|