source: branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireFileMetaData.m @ 756

Revision 756, 25.2 KB checked in by gbooker, 5 years ago (diff)

If we have no other text to display on the right, the duration is more useful than the file size.

Line 
1#import "SapphireFileMetaData.h"
2#import "SapphireXMLData.h"
3#import "SapphireMovie.h"
4#import "SapphireEpisode.h"
5#import "SapphireDirectoryMetaData.h"
6#import "SapphireVideoTsParser.h"
7#import "SapphireMetaDataSupport.h"
8#import "SapphireMediaPreview.h"
9#import "SapphireFileSymLink.h"
10#import "SapphireSettings.h"
11#import "CoreDataSupportFunctions.h"
12
13#import "SapphireTVShow.h"
14#import "SapphireTVTranslation.h"
15#import "SapphireMovieTranslation.h"
16
17#import <QTKit/QTKit.h>
18
19@implementation SapphireFileMetaData
20
21//ATV Extra Info;
22NSString *META_SHOW_BROADCASTER_KEY =           @"Broadcast Company";
23NSString *META_SHOW_PUBLISHED_DATE_KEY =        @"Published Date";
24NSString *META_SHOW_AQUIRED_DATE =                      @"Date Aquired";
25NSString *META_SHOW_RATING_KEY =                        @"Rating";
26NSString *META_SHOW_FAVORITE_RATING_KEY =       @"User Rating";
27NSString *META_COPYRIGHT_KEY =                          @"Copyright";
28
29//IMDB Type Info;
30NSString *META_MOVIE_TITLE_KEY =                                @"Title";
31NSString *META_MOVIE_CAST_KEY =                                 @"Cast";
32NSString *META_MOVIE_RELEASE_DATE_KEY =                 @"Release Date";
33NSString *META_MOVIE_DIRECTOR_KEY =                             @"Director";
34NSString *META_MOVIE_WIRTERS_KEY =                              @"Writers";
35NSString *META_MOVIE_GENRES_KEY =                               @"Genres";
36NSString *META_MOVIE_PLOT_KEY =                                 @"Plot";
37NSString *META_MOVIE_IMDB_RATING_KEY =                  @"IMDB Rating";
38NSString *META_MOVIE_IMDB_250_KEY =                             @"IMDB Top 250";
39NSString *META_MOVIE_MPAA_RATING_KEY =                  @"MPAA Rating";
40NSString *META_MOVIE_OSCAR_KEY =                                @"Oscars";
41NSString *META_MOVIE_IDENTIFIER_KEY =                   @"Movie ID";
42
43//TV Show Specific Keys;
44NSString *META_TITLE_KEY =                                      @"Title";
45NSString *META_SEASON_NUMBER_KEY =                      @"Season";
46NSString *META_EPISODE_NUMBER_KEY =                     @"Episode";
47NSString *META_SHOW_NAME_KEY =                          @"Show Name";
48NSString *META_DESCRIPTION_KEY =                        @"Show Description";
49NSString *META_SHOW_AIR_DATE =                          @"Air Date";
50NSString *META_RATING_KEY =                                     @"Rating";
51NSString *META_SUMMARY_KEY =                            @"Summary";
52NSString *META_ABSOLUTE_EP_NUMBER_KEY =         @"Episode Number";
53NSString *META_SHOW_IDENTIFIER_KEY =            @"Show ID";
54NSString *META_EPISODE_2_NUMBER_KEY =           @"Episode 2";
55NSString *META_ABSOLUTE_EP_2_NUMBER_KEY =       @"Episode Number 2";
56NSString *META_SEARCH_SEASON_NUMBER_KEY =       @"Search Season";
57NSString *META_SEARCH_EPISODE_NUMBER_KEY =      @"Search Episode";
58NSString *META_SEARCH_EPISODE_2_NUMBER_KEY =    @"Search Episode 2";
59NSString *FILE_CLASS_KEY =                                      @"File Class";
60
61//File Specific Keys
62#define MODIFIED_KEY                            @"Modified"
63#define WATCHED_KEY                                     @"Watched"
64#define FAVORITE_KEY                            @"Favorite"
65#define RESUME_KEY                                      @"Resume Time"
66#define SIZE_KEY                                        @"Size"
67#define DURATION_KEY                            @"Duration"
68#define AUDIO_DESC_KEY                          @"Audio Description"
69#define SAMPLE_RATE_KEY                         @"Sample Rate"
70#define VIDEO_DESC_KEY                          @"Video Description"
71#define AUDIO_FORMAT_KEY                        @"Audio Format"
72#define SUBTITLES_KEY                           @"Subtitles"
73#define JOINED_FILE_KEY                         @"Joined File"
74
75static NSSet *displayedMetaData;
76static NSArray *displayedMetaDataOrder;
77
78+ (void)load
79{
80        displayedMetaDataOrder = [[NSArray alloc] initWithObjects:
81                                                          META_MOVIE_IMDB_250_KEY,
82                                                          META_MOVIE_IMDB_RATING_KEY,                                     
83                                                          META_MOVIE_DIRECTOR_KEY,
84                                                          META_MOVIE_CAST_KEY,
85                                                          META_MOVIE_GENRES_KEY,
86                                                          META_EPISODE_AND_SEASON_KEY,
87                                                          META_SEASON_NUMBER_KEY,
88                                                          META_EPISODE_NUMBER_KEY,
89                                                          META_MOVIE_IMDB_STATS_KEY,
90                                                          SIZE_KEY,
91                                                          DURATION_KEY,
92                                                          VIDEO_DESC_LABEL_KEY,
93                                                          AUDIO_DESC_LABEL_KEY,
94                                                          SUBTITLES_KEY,
95                                                          nil];
96        displayedMetaData = [[NSSet alloc] initWithArray:displayedMetaDataOrder];       
97}
98
99+ (SapphireFileMetaData *)fileWithPath:(NSString *)path inContext:(NSManagedObjectContext *)moc
100{
101        SapphireMetaData *meta = [SapphireMetaData metaDataWithPath:path inContext:moc];
102        if([meta isKindOfClass:[SapphireFileMetaData class]])
103                return (SapphireFileMetaData *)meta;
104        return nil;
105}
106
107+ (SapphireFileMetaData *)internalCreateFileWithPath:(NSString *)path parent:(SapphireDirectoryMetaData *)parent inContext:(NSManagedObjectContext *)moc
108{
109        SapphireFileMetaData *ret = [NSEntityDescription insertNewObjectForEntityForName:SapphireFileMetaDataName inManagedObjectContext:moc];
110        ret.parent = parent;
111        ret.path = path;
112       
113        return ret;
114}
115
116+ (SapphireFileMetaData *)createFileWithPath:(NSString *)path inContext:(NSManagedObjectContext *)moc
117{
118        SapphireFileMetaData *ret = [SapphireFileMetaData fileWithPath:path inContext:moc];
119        if(ret != nil)
120                return ret;
121       
122        SapphireDirectoryMetaData *parent = [SapphireDirectoryMetaData createDirectoryWithPath:[path stringByDeletingLastPathComponent] inContext:moc];
123        ret = [SapphireFileMetaData internalCreateFileWithPath:path parent:parent inContext:moc];
124       
125        return ret;
126}
127
128+ (SapphireFileMetaData *)createFileWithPath:(NSString *)path parent:(SapphireDirectoryMetaData *)parent inContext:(NSManagedObjectContext *)moc
129{
130        SapphireFileMetaData *ret = [SapphireFileMetaData fileWithPath:path inContext:moc];
131        if(ret != nil)
132                return ret;
133       
134        return [SapphireFileMetaData internalCreateFileWithPath:path parent:parent inContext:moc];
135}
136
137+ (NSDictionary *)upgradeV1FilesFromContext:(NSManagedObjectContext *)oldMoc toContext:(NSManagedObjectContext *)newMoc withMovies:(NSDictionary *)movieLookup directories:(NSDictionary *)dirLookup
138{
139        NSMutableDictionary *lookup = [NSMutableDictionary dictionary];
140        NSArray *files = doFetchRequest(SapphireFileMetaDataName, oldMoc, nil);
141        NSEnumerator *fileEnum = [files objectEnumerator];
142        NSManagedObject *oldFile;
143        while((oldFile = [fileEnum nextObject]) != nil)
144        {
145                SapphireFileMetaData *newFile = [NSEntityDescription insertNewObjectForEntityForName:SapphireFileMetaDataName inManagedObjectContext:newMoc];
146                NSString *path = [oldFile valueForKey:@"path"];
147                newFile.path = path;
148                newFile.parent = [dirLookup objectForKey:[oldFile valueForKeyPath:@"parent.path"]];
149                newFile.audioDescription = [oldFile valueForKey:@"audioDescription"];
150                newFile.audioFormatID = [oldFile valueForKey:@"audioFormatID"];
151                newFile.duration = [oldFile valueForKey:@"duration"];
152                newFile.favorite = [oldFile valueForKey:@"favorite"];
153                newFile.fileClass = [oldFile valueForKey:@"fileClass"];
154                newFile.fileContainerType = [oldFile valueForKey:@"fileContainerType"];
155                newFile.hasVideo = [oldFile valueForKey:@"hasVideo"];
156                newFile.importTypeValue = [[oldFile valueForKey:@"importType"] intValue] & ~IMPORT_TYPE_XML_MASK;
157                newFile.modified = [oldFile valueForKey:@"modified"];
158                newFile.resumeTime = [oldFile valueForKey:@"resumeTime"];
159                newFile.sampleRate = [oldFile valueForKey:@"sampleRate"];
160                newFile.size = [oldFile valueForKey:@"size"];
161                newFile.subtitlesDescription = [oldFile valueForKey:@"subtitlesDescription"];
162                newFile.videoDescription = [oldFile valueForKey:@"videoDescription"];
163                newFile.watched = [oldFile valueForKey:@"watched"];
164                NSNumber *oldMovieNumber = [oldFile valueForKeyPath:@"movie.imdbNumber"];
165                if(oldMovieNumber != nil)
166                        newFile.movie = [movieLookup objectForKey:oldMovieNumber];
167               
168                [lookup setObject:newFile forKey:path];
169        }
170        return lookup;
171}
172
173- (void)insertDictionary:(NSDictionary *)dict withDefer:(NSMutableDictionary *)defer
174{
175        self.audioDescription = [dict objectForKey:AUDIO_DESC_KEY];
176        self.audioFormatID = [dict objectForKey:AUDIO_FORMAT_KEY];
177        self.duration = [dict objectForKey:DURATION_KEY];
178        self.favoriteValue = [[dict objectForKey:FAVORITE_KEY] boolValue];
179        self.fileClass = [dict objectForKey:@"File Class"];
180        self.fileContainerType = [dict objectForKey:@"File Container Type"];
181        id value = [dict objectForKey:MODIFIED_KEY];
182        if(value != nil)
183                self.modified = [NSDate dateWithTimeIntervalSince1970:[value intValue]];
184        self.resumeTimeValue = [[dict objectForKey:RESUME_KEY] unsignedIntValue];
185        self.sampleRate = [dict objectForKey:SAMPLE_RATE_KEY];
186        self.size = [dict objectForKey:SIZE_KEY];
187        self.subtitlesDescription = [dict objectForKey:SUBTITLES_KEY];
188        self.videoDescription = [dict objectForKey:VIDEO_DESC_KEY];
189        self.watchedValue = [[dict objectForKey:WATCHED_KEY] boolValue];
190        self.hasVideoValue = self.videoDescription != nil;
191        value = [dict objectForKey:@"XML Source"];
192        if(value != nil)
193        {
194                NSDictionary *xmlDict = (NSDictionary *)value;
195                SapphireXMLData *xml = self.xmlData;
196                if(xml == nil)
197                {
198                        xml = [NSEntityDescription insertNewObjectForEntityForName:SapphireXMLDataName inManagedObjectContext:[self managedObjectContext]];
199                        self.xmlData = xml;
200                }
201                [xml insertDictionary:xmlDict];
202                xml.modified = [NSDate dateWithTimeIntervalSince1970:[[xmlDict objectForKey:MODIFIED_KEY] intValue]];
203                self.importTypeValue |= IMPORT_TYPE_XML_MASK;
204        }
205        value = [dict objectForKey:@"TVRage Source"];
206        if(value != nil)
207        {
208                SapphireEpisode *ep = [SapphireEpisode episodeWithDictionary:(NSDictionary *)value inContext:[self managedObjectContext]];
209                self.tvEpisode = ep;
210                if(ep != nil)
211                {
212                        self.fileClassValue = FILE_CLASS_TV_SHOW;
213                        NSString *epCoverPath = [[SapphireMetaDataSupport collectionArtPath] stringByAppendingPathComponent:[ep path]];
214                        NSString *oldBasePath = [[epCoverPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:[self.path lastPathComponent]];
215                        NSString *oldCoverPath = searchCoverArtExtForPath([oldBasePath stringByDeletingPathExtension]);
216                        if(oldCoverPath != nil)
217                        {
218                                NSString *newPath = [epCoverPath stringByAppendingPathExtension:[oldCoverPath pathExtension]];
219                                NSFileManager *fm = [NSFileManager defaultManager];
220                                [fm movePath:oldCoverPath toPath:newPath handler:nil];
221                        }
222                }
223                self.importTypeValue |= IMPORT_TYPE_TVSHOW_MASK;
224        }
225        value = [dict objectForKey:@"IMDB Source"];
226        if(value != nil)
227        {
228                SapphireMovie *movie = [SapphireMovie movieWithDictionary:(NSDictionary *)value inContext:[self managedObjectContext] lookup:defer];
229                self.movie = movie;
230                if(movie != nil)
231                {
232                        self.fileClassValue = FILE_CLASS_MOVIE;
233                        NSString *movieCoverPath = [movie coverArtPath];
234                        NSString *oldBasePath = [[[SapphireMetaDataSupport collectionArtPath] stringByAppendingPathComponent:@"@MOVIES"] stringByAppendingPathComponent:[self.path lastPathComponent]];
235                        NSString *oldCoverPath = searchCoverArtExtForPath([oldBasePath stringByDeletingPathExtension]);
236                        if(oldCoverPath != nil)
237                        {
238                                NSString *newPath = [movieCoverPath stringByAppendingPathExtension:[oldCoverPath pathExtension]];
239                                NSFileManager *fm = [NSFileManager defaultManager];
240                                [fm movePath:oldCoverPath toPath:newPath handler:nil];
241                        }
242                }
243                self.importTypeValue |= IMPORT_TYPE_MOVIE_MASK;
244        }
245        NSString *joinPath = [dict objectForKey:JOINED_FILE_KEY];
246        if(joinPath != nil)
247        {
248                NSMutableDictionary *joinDict = [defer objectForKey:@"Join"];
249                NSMutableArray *joinList = [joinDict objectForKey:joinPath];
250                if(joinList == nil)
251                {
252                        joinList = [NSMutableArray array];
253                        [joinDict setObject:joinList forKey:joinPath];
254                }
255                [joinList addObject:self];
256        }
257}
258
259/*Custom TV Episode handler*/
260- (NSComparisonResult) episodeCompare:(SapphireFileMetaData *)other
261{
262        /*Sort by episode*/
263        SapphireEpisode *myEp = self.tvEpisode;
264        SapphireEpisode *theirEp = nil;
265        if([other isKindOfClass:[SapphireFileSymLink class]])
266                theirEp = ((SapphireFileSymLink *)other).file.tvEpisode;
267        else
268                theirEp = other.tvEpisode;
269       
270        if(myEp != nil)
271        {
272                if(theirEp != nil)
273                        return [myEp compare:theirEp];
274                else
275                        return NSOrderedAscending;
276        }
277        else if (theirEp != nil)
278                return NSOrderedDescending;
279
280        return NSOrderedSame;
281}
282
283- (NSComparisonResult) movieCompare:(SapphireFileMetaData *)other
284{
285        SapphireMovie *myMovie = self.movie;
286        SapphireMovie *theirMovie = other.movie;
287       
288        if(myMovie != nil)
289                if(theirMovie != nil)
290                {
291                        NSComparisonResult ret = [myMovie titleCompare:theirMovie];
292                        if(ret == NSOrderedSame)
293                                ret = [myMovie releaseDateCompare:theirMovie];
294                        return ret;
295                }
296                else
297                        return NSOrderedAscending;
298        else if(theirMovie != nil)
299                return NSOrderedDescending;
300       
301        return NSOrderedSame;
302}
303
304- (BOOL) needsUpdating
305{
306        /*Check modified date*/
307        NSDictionary *props = [[NSFileManager defaultManager] fileAttributesAtPath:self.path traverseLink:YES];
308        int modTime = [[props objectForKey:NSFileModificationDate] timeIntervalSince1970];
309       
310        if(props == nil)
311        /*No file*/
312                return FALSE;
313       
314        /*Has it been modified since last import?*/
315        return modTime != [self.modified timeIntervalSince1970];
316}
317
318- (oneway void)addFileData:(bycopy NSDictionary *)fileMeta
319{
320        self.audioDescription = [fileMeta objectForKey:AUDIO_DESC_KEY];
321        self.audioFormatID = [fileMeta objectForKey:AUDIO_FORMAT_KEY];
322        self.duration = [fileMeta objectForKey:DURATION_KEY];
323        id value = [fileMeta objectForKey:MODIFIED_KEY];
324        if(value != nil)
325                self.modified = [NSDate dateWithTimeIntervalSince1970:[value intValue]];
326        self.sampleRate = [fileMeta objectForKey:SAMPLE_RATE_KEY];
327        self.size = [fileMeta objectForKey:SIZE_KEY];
328        self.subtitlesDescription = [fileMeta objectForKey:SUBTITLES_KEY];
329        NSString *videoDesc = [fileMeta objectForKey:VIDEO_DESC_KEY];
330        self.videoDescription = videoDesc;
331        if(videoDesc != nil)
332                self.hasVideoValue = YES;
333}
334
335
336BOOL updateMetaData(SapphireFileMetaData *file)
337{
338        BOOL updated =FALSE;
339        if([file needsUpdating])
340        {
341                /*We did an update*/
342                updated=TRUE ;
343                NSMutableDictionary *fileMeta = [NSMutableDictionary dictionary];
344                NSString *path = [file path];
345               
346                NSDictionary *props = [[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES];
347                int modTime = [[props objectForKey:NSFileModificationDate] timeIntervalSince1970];
348                /*Set modified, size, and version*/
349                [fileMeta setObject:[NSNumber numberWithInt:modTime] forKey:MODIFIED_KEY];
350                [fileMeta setObject:[props objectForKey:NSFileSize] forKey:SIZE_KEY];
351               
352                if([file fileContainerTypeValue] == FILE_CONTAINER_TYPE_QT_MOVIE)
353                {
354                        /*Open the movie*/
355                        NSError *error = nil;
356                        QTMovie *movie = [QTMovie movieWithFile:path error:&error];
357                        QTTime duration = [movie duration];
358                        [fileMeta setObject:[NSNumber numberWithFloat:(float)duration.timeValue/(float)duration.timeScale] forKey:DURATION_KEY];
359                        NSArray *audioTracks = [movie tracksOfMediaType:@"soun"];
360                        NSNumber *audioSampleRate = nil;
361                        if([audioTracks count])
362                        {
363                                /*Get the audio track*/
364                                QTTrack *track = [audioTracks objectAtIndex:0];
365                                QTMedia *media = [track media];
366                                if(media != nil)
367                                {
368                                        /*Get the audio format*/
369                                        Media qtMedia = [media quickTimeMedia];
370                                        Handle sampleDesc = NewHandle(1);
371                                        GetMediaSampleDescription(qtMedia, 1, (SampleDescriptionHandle)sampleDesc);
372                                        AudioStreamBasicDescription asbd;
373                                        ByteCount       propSize = 0;
374                                        QTSoundDescriptionGetProperty((SoundDescriptionHandle)sampleDesc, kQTPropertyClass_SoundDescription, kQTSoundDescriptionPropertyID_AudioStreamBasicDescription, sizeof(asbd), &asbd, &propSize);
375                                       
376                                        if(propSize != 0)
377                                        {
378                                                /*Set the format and sample rate*/
379                                                NSNumber *format = [NSNumber numberWithUnsignedInt:asbd.mFormatID];
380                                                [fileMeta setObject:format forKey:AUDIO_FORMAT_KEY];
381                                                audioSampleRate = [NSNumber numberWithDouble:asbd.mSampleRate];
382                                        }
383                                       
384                                        CFStringRef userText = nil;
385                                        propSize = 0;
386                                        QTSoundDescriptionGetProperty((SoundDescriptionHandle)sampleDesc, kQTPropertyClass_SoundDescription, kQTSoundDescriptionPropertyID_UserReadableText, sizeof(userText), &userText, &propSize);
387                                        if(userText != nil)
388                                        {
389                                                /*Set the description*/
390                                                [fileMeta setObject:(NSString *)userText forKey:AUDIO_DESC_KEY];
391                                                CFRelease(userText);
392                                        }
393                                        DisposeHandle(sampleDesc);
394                                }
395                        }
396                        /*Set the sample rate*/
397                        if(audioSampleRate != nil)
398                                [fileMeta setObject:audioSampleRate forKey:SAMPLE_RATE_KEY];
399                        NSArray *videoTracks = [movie tracksOfMediaType:@"vide"];
400                        if([videoTracks count])
401                        {
402                                /*Get the video track*/
403                                QTTrack *track = [videoTracks objectAtIndex:0];
404                                QTMedia *media = [track media];
405                                if(media != nil)
406                                {
407                                        /*Get the video description*/
408                                        Media qtMedia = [media quickTimeMedia];
409                                        Handle sampleDesc = NewHandle(1);
410                                        GetMediaSampleDescription(qtMedia, 1, (SampleDescriptionHandle)sampleDesc);
411                                        CFStringRef userText = nil;
412                                        ByteCount propSize = 0;
413                                        ICMImageDescriptionGetProperty((ImageDescriptionHandle)sampleDesc, kQTPropertyClass_ImageDescription, kICMImageDescriptionPropertyID_SummaryString, sizeof(userText), &userText, &propSize);
414                                        DisposeHandle(sampleDesc);
415                                       
416                                        if(userText != nil)
417                                        {
418                                                /*Set the description*/
419                                                [fileMeta setObject:(NSString *)userText forKey:VIDEO_DESC_KEY];
420                                                CFRelease(userText);
421                                        }
422                                }
423                        }
424                } //QTMovie
425                else if([file fileContainerTypeValue] == FILE_CONTAINER_TYPE_VIDEO_TS)
426                {
427                        SapphireVideoTsParser *dvd = [[SapphireVideoTsParser alloc] initWithPath:path];
428                       
429                        [fileMeta setObject:[dvd videoFormatsString ] forKey:VIDEO_DESC_KEY];
430                        [fileMeta setObject:[dvd audioFormatsString ] forKey:AUDIO_DESC_KEY];
431                        [fileMeta setObject:[dvd subtitlesString    ] forKey:SUBTITLES_KEY ];
432                        [fileMeta setObject:[dvd mainFeatureDuration] forKey:DURATION_KEY  ];
433                        [fileMeta setObject:[dvd totalSize          ] forKey:SIZE_KEY      ];
434                       
435                        [dvd release];
436                } // VIDEO_TS
437                [file addFileData:fileMeta];
438        }
439        return updated;
440}
441
442- (BOOL)updateMetaData
443{
444        return updateMetaData(self);
445}
446
447- (NSString *)sizeString
448{
449        /*Get size*/
450        float size = [self sizeValue];
451        if(size == 0)
452                return @"-";
453       
454        /*The letter for magnitude*/
455        char letter = ' ';
456        if(size >= 1024000)
457        {
458                if(size >= 1024*1024000)
459                {
460                        /*GB*/
461                        size /= 1024 * 1024 * 1024;
462                        letter = 'G';
463                }
464                else
465                {
466                        /*MB*/
467                        size /= 1024 * 1024;
468                        letter = 'M';
469                }
470        }
471        else if (size >= 1000)
472        {
473                /*KB*/
474                size /= 1024;
475                letter = 'K';
476        }
477        return [NSString stringWithFormat:@"%.1f%cB", size, letter];   
478}
479
480- (void)setToReimportFromMask:(int)mask
481{
482        int currentMask = self.importTypeValue;
483        self.importTypeValue = currentMask & ~mask;
484        if(mask & IMPORT_TYPE_MOVIE_MASK)
485        {
486                SapphireMovie *movie = self.movie;
487                self.movie = nil;
488                if(movie != nil && [movie.filesSet count] == 0)
489                        [[self managedObjectContext] deleteObject:movie];
490        }
491        if(mask & IMPORT_TYPE_TVSHOW_MASK)
492        {
493                SapphireEpisode *ep = self.tvEpisode;
494                self.tvEpisode = nil;
495                if(ep != nil && [ep.filesSet count] == 0)
496                        [[self managedObjectContext] deleteObject:ep];
497        }
498}
499
500- (void)setToResetImportDecisions
501{
502        NSManagedObjectContext *moc = [self managedObjectContext];
503        NSString *lowerFileName = [[self.path lastPathComponent] lowercaseString];
504
505        SapphireEpisode *ep = self.tvEpisode;
506        if(ep != nil)
507        {
508                NSSet *translations = ep.tvShow.translationsSet;
509                SapphireTVTranslation *tran;
510                NSEnumerator *tranEnum = [translations objectEnumerator];
511                while((tran = [tranEnum nextObject]) != nil)
512                {
513                        if([lowerFileName hasPrefix:tran.name])
514                        {
515                                SapphireLog(SAPPHIRE_LOG_METADATA_STORE, SAPPHIRE_LOG_LEVEL_DETAIL, @"Deleting TV import translation for %@", tran.name);
516                                [moc deleteObject:tran];
517                        }
518                }
519        }
520        NSString *lookupName;
521        if([[SapphireSettings sharedSettings] dirLookup])
522                lookupName = [[[self.path stringByDeletingLastPathComponent] lastPathComponent] lowercaseString];
523        else
524                lookupName = lowerFileName;
525        SapphireMovieTranslation *movieTran = [SapphireMovieTranslation movieTranslationWithName:[lookupName stringByDeletingPathExtension] inContext:moc];
526        if(movieTran != nil)
527        {
528                SapphireLog(SAPPHIRE_LOG_METADATA_STORE, SAPPHIRE_LOG_LEVEL_DETAIL, @"Deleting Movie import translation for %@", movieTran.name);
529                [moc deleteObject:movieTran];
530        }
531       
532        [self setToReimportFromMask:IMPORT_TYPE_ALL_MASK];
533}
534
535- (void)clearMetaData
536{
537        self.audioDescription = nil;
538        self.audioFormatID = nil;
539        self.duration = nil;
540        self.favoriteValue = 0;
541        self.fileClassValue = nil;
542        self.fileContainerType = nil;
543        self.hasVideo = nil;
544        self.importTypeValue = 0;
545        self.modified = nil;
546        self.resumeTime = nil;
547        self.sampleRate = nil;
548        self.size = nil;
549        self.subtitlesDescription = nil;
550        self.videoDescription = nil;
551        self.watchedValue = 0;
552        self.movie = nil;
553        self.tvEpisode = nil;
554        if(self.xmlData != nil)
555        {
556                [[self managedObjectContext] deleteObject:self.xmlData];
557        }
558}
559
560- (NSString *)coverArtPath
561{
562        /*Find cover art for the current file in the "Cover Art" dir */
563        NSString *subPath = [self path];
564        if([self fileContainerTypeValue] != FILE_CONTAINER_TYPE_VIDEO_TS)
565                subPath = [subPath stringByDeletingPathExtension];
566       
567        NSString *fileName = [subPath lastPathComponent];
568        NSString * myArtPath=nil;
569       
570        if([self fileClassValue]==FILE_CLASS_TV_SHOW)
571                myArtPath=[[self tvEpisode] coverArtPath];
572        if([self fileClassValue]==FILE_CLASS_MOVIE)
573                myArtPath=[[self movie] coverArtPath];
574       
575        /* Check the Collection Art location */
576        NSString *ret=searchCoverArtExtForPath(myArtPath);
577       
578        if(ret != nil)
579                return ret;
580       
581        /* Try Legacy Folders with the file */
582        ret=searchCoverArtExtForPath([[[subPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"Cover Art"] stringByAppendingPathComponent:fileName]);
583       
584        if(ret != nil)
585                return ret;
586       
587        /*Find cover art for the current file in the current dir*/
588        ret = searchCoverArtExtForPath(subPath);
589       
590        if(ret != nil)
591                return ret;
592       
593       
594        return nil;
595}
596
597- (NSString *)durationString
598{
599        /*Create duration string*/
600        int duration = [self durationValue];
601        int secs = duration % 60;
602        int mins = (duration /60) % 60;
603        int hours = duration / 3600;
604        NSString *durationStr = nil;
605        if(hours != 0)
606                durationStr = [NSString stringWithFormat:@"%d:%02d:%02d", hours, mins, secs];
607        else if (mins != 0)
608                durationStr = [NSString stringWithFormat:@"%d:%02d", mins, secs];
609        else
610                durationStr = [NSString stringWithFormat:@"%ds", secs];
611        return durationStr;
612}
613
614- (NSMutableDictionary *)getDisplayedMetaDataInOrder:(NSArray * *)order;
615{
616        NSString *name = [[self path] lastPathComponent];
617        NSString *durationStr = [self durationString];
618        /*Set the order*/
619        if(order != nil)
620                *order = displayedMetaDataOrder;
621       
622        NSMutableDictionary *ret = [[NSMutableDictionary alloc] init];
623       
624        SapphireMovie *movie = [self movie];
625        SapphireEpisode *ep = [self tvEpisode];
626        if(movie != nil)
627        {
628                [movie insertDisplayMetaData:ret];
629        }
630        else if (ep != nil)
631        {
632                [ep insertDisplayMetaData:ret];
633        }
634       
635        id value = [self videoDescription];
636        if(value != nil)
637                [ret setObject:value forKey:VIDEO_DESC_LABEL_KEY];
638        value = [self audioDescription];
639        if(value != nil)
640                [ret setObject:value forKey:AUDIO_DESC_LABEL_KEY];
641        value = [self subtitlesDescription];
642        if(value != nil)
643                [ret setObject:value forKey:SUBTITLES_KEY];
644        if([self durationValue])
645        {
646                if([self sizeValue])
647                        [ret setObject:[NSString stringWithFormat:@"%@ (%@)", durationStr, [self sizeString]] forKey:BRLocalizedString(DURATION_KEY, @"file duration in metadata display")];
648                else
649                        [ret setObject:durationStr forKey:BRLocalizedString(DURATION_KEY, @"file duration in metadata display")];
650        }
651        else
652                [ret setObject:[self sizeString] forKey:BRLocalizedString(SIZE_KEY, @"filesize in metadata display")];
653       
654        /*Set the title*/
655        if([ret objectForKey:META_TITLE_KEY] == nil)
656                [ret setObject:name forKey:META_TITLE_KEY];
657        return [ret autorelease];
658}
659
660- (NSString *)searchShowName
661{
662        return self.xmlData.searchShowName;
663}
664
665- (int)searchSeasonNumber
666{
667        NSNumber *value = self.xmlData.searchSeasonNumber;
668        if(value != nil)
669                return [value intValue];
670        return -1;
671}
672
673- (int)searchEpisodeNumber
674{
675        NSNumber *value = self.xmlData.searchEpisode;
676        if(value != nil)
677                return [value intValue];
678        return -1;
679}
680
681- (int)searchLastEpisodeNumber
682{
683        NSNumber *value = self.xmlData.searchLastEpisodeNumber;
684        if(value != nil)
685                return [value intValue];
686        return -1;
687}
688
689- (int)searchIMDBNumber
690{
691        NSNumber *value = self.xmlData.searchIMDBNumber;
692        if(value != nil)
693                return [value intValue];
694        return -1;
695}
696
697- (FileContainerType)fileContainerTypeValue
698{
699        return super.fileContainerTypeValue;
700}
701
702- (ImportTypeMask)importTypeValue
703{
704        return super.importTypeValue;
705}
706
707- (long)importedTimeFromSource:(int)source
708{
709        if(source == IMPORT_TYPE_FILE_MASK)
710                return [self.modified timeIntervalSince1970];
711        else if(source == IMPORT_TYPE_XML_MASK)
712                return [self.xmlData.modified timeIntervalSince1970];
713        return 0;
714}
715
716- (void)didImportType:(ImportTypeMask)type
717{
718        self.importTypeValue |= type;
719}
720
721- (void)setMovie:(SapphireMovie *)movie
722{
723        SapphireMovie *oldMovie = self.movie;
724        super.movie = movie;
725        if(movie != nil)
726        {
727                [self setFileClassValue:FILE_CLASS_MOVIE];
728                self.importTypeValue |= IMPORT_TYPE_MOVIE_MASK;
729        }
730        if(movie != oldMovie)
731        {
732                self.xmlData.movie = movie;
733                [movie clearPredicateCache];
734                [oldMovie clearPredicateCache];
735                [[NSNotificationCenter defaultCenter] postNotificationName:FILE_DID_CHANGE_MOVIE_NOTIFICATION object:self];
736        }
737}
738
739- (void)setTvEpisode:(SapphireEpisode *)ep
740{
741        SapphireEpisode *oldEp = self.tvEpisode;
742        super.tvEpisode = ep;
743        if(ep != nil)
744        {
745                [self setFileClassValue:FILE_CLASS_TV_SHOW];
746                self.importTypeValue |= IMPORT_TYPE_TVSHOW_MASK;
747                [ep clearPredicateCache];
748        }
749        if(ep != oldEp)
750                self.xmlData.episode = ep;
751        [oldEp clearPredicateCache];
752}
753
754- (void)setXmlData:(SapphireXMLData *)data
755{
756        super.xmlData = data;
757        if(data != nil)
758        {
759                data.episode = self.tvEpisode;
760                data.movie = self.movie;
761        }
762}
763
764- (FileClass)fileClassValue
765{
766        FileClass xmlClass = self.xmlData.fileClassValue;
767        if(xmlClass != FILE_CLASS_UNKNOWN)
768                return xmlClass;
769        return super.fileClassValue;
770}
771
772- (void)setFileClassValue:(FileClass)fileClass
773{
774        FileClass xmlClass = self.xmlData.fileClassValue;
775        if(xmlClass != FILE_CLASS_UNKNOWN)
776                self.xmlData.fileClassValue = FILE_CLASS_UNKNOWN;
777        super.fileClassValue = fileClass;
778}
779
780- (void)setWatched:(NSNumber*)value_ {
781        NSNumber *oldValue = [self.watched retain];
782        super.watched = value_;
783        if(![oldValue isEqualToNumber:value_])
784        {
785                [self.parent clearPredicateCache];
786                [self.tvEpisode clearPredicateCache];
787                [self.movie clearPredicateCache];
788        }
789}
790
791- (void)setFavorite:(NSNumber*)value_ {
792        NSNumber *oldValue = [self.favorite retain];
793        super.favorite = value_;
794        if(![oldValue isEqualToNumber:value_])
795        {
796                [self.parent clearPredicateCache];
797                [self.tvEpisode clearPredicateCache];
798                [self.movie clearPredicateCache];
799        }
800}
801
802@end
Note: See TracBrowser for help on using the repository browser.