source: trunk/SapphireMediaPreview.m @ 252

Revision 252, 10.3 KB checked in by pmerrill, 7 years ago (diff)
  • Added a media preview for movie specific metadata.
  • Code cleanup.


Line 
1//
2//  SapphireMediaPreview.m
3//  Sapphire
4//
5//  Created by Graham Booker on 6/26/07.
6//  Copyright 2007 www.nanopi.net. All rights reserved.
7//
8
9#import "SapphireMediaPreview.h"
10#import "SapphireMetaData.h"
11#import "SapphireMedia.h"
12#import "SapphireSettings.h"
13#import <objc/objc-class.h>
14
15/*These interfaces are to access variables not available*/
16@interface BRMetadataLayer (protectedAccess)
17- (NSArray *)gimmieMetadataObjs;
18@end
19
20@implementation BRMetadataLayer (protectedAccess)
21- (NSArray *)gimmieMetadataObjs
22{
23        Class myClass = [self class];
24        Ivar ret = class_getInstanceVariable(myClass,"_metadataLabels");
25       
26        return *(NSArray * *)(((char *)self)+ret->ivar_offset);
27}
28@end
29
30@implementation SapphireMediaPreview
31
32/*List of extensions to look for cover art*/
33static NSSet *coverArtExtentions = nil;
34
35+ (void)initialize
36{
37        /*Initialize the set of cover art extensions*/
38        coverArtExtentions = [[NSSet alloc] initWithObjects:
39                @"jpg",
40                @"jpeg",
41                @"tif",
42                @"tiff",
43                @"png",
44                @"gif",
45                nil];
46}
47
48- (void)dealloc
49{
50        [meta release];
51        [super dealloc];
52}
53
54/*!
55 * @brief Set the File information
56 *
57 * @param newMeta The meta data
58 */
59- (void)setMetaData:(SapphireMetaData *)newMeta
60{
61        [meta release];
62        NSString *path = [newMeta path];
63        if(path == nil)
64        {
65                meta = nil;
66                return;
67        }
68        meta = [newMeta retain];
69        /*Now that we know the file, set the asset*/
70        NSURL *url = [NSURL fileURLWithPath:[meta path]];
71        SapphireMedia *asset  =[[SapphireMedia alloc] initWithMediaURL:url];
72        [self setAsset:asset];
73}
74
75/*!
76 * @brief Search for cover art in the current path
77 *
78 * @param path Path to search for cover art, minus the extension
79 * @return The path to the found cover art
80 */
81- (NSString *)searchExtForPath:(NSString *)path
82{
83        NSFileManager *fm = [NSFileManager defaultManager];
84        BOOL isDir = NO;
85        /*Search all extensions*/
86        NSEnumerator *extEnum = [coverArtExtentions objectEnumerator];
87        NSString *ext = nil;
88        while((ext = [extEnum nextObject]) != nil)
89        {
90                NSString *candidate = [path stringByAppendingPathExtension:ext];
91                /*Check the candidate*/
92                if([fm fileExistsAtPath:candidate isDirectory:&isDir] && !isDir)
93                        return candidate;
94        }
95        /*Didn't find one*/
96        return nil;
97}
98
99/*!
100 * @brief Searches for the directory's cover art
101 *
102 * @param dir the directory to search
103 * @param parents the number of parent directories to search after this one
104 * @return The path to the found cover art
105 */
106- (NSString *)coverArtForDir:(NSString *)dir parents:(int)parents
107{
108        /*Check for cover.ext in the "Cover Art" dir*/
109        NSString *ret = [self searchExtForPath:[dir stringByAppendingPathComponent:@"Cover Art/cover"]];
110        if(ret != nil)
111                return ret;
112        /*Next check for cover.ext in the current dir*/
113        ret = [self searchExtForPath:[dir stringByAppendingPathComponent:@"cover"]];
114        if(ret != nil)
115                return ret;
116        /*Finally, try going up a dir*/
117        if(parents != 0)
118                return [self coverArtForDir:[dir stringByDeletingLastPathComponent] parents:parents -1];
119        /*Didn't find one*/
120        return nil;
121}
122
123/*!
124 * @brief Search for cover art for the current metadata
125 *
126 * @return The path to the found cover art
127 */
128- (NSString *)coverArtForPath
129{
130        /*See if this is a directory*/
131        if([meta isKindOfClass:[SapphireDirectoryMetaData class]])
132        {
133                /*Search for cover art for the current directory or a single parent dir*/
134                NSString *ret = [self coverArtForDir:[meta path] parents:1];
135                if(ret != nil)
136                        return ret;
137                /*Fallback to default*/
138                return [[[NSBundle bundleForClass:[self class]] bundlePath] stringByAppendingString:@"/Contents/Resources/DefaultPreview.png"];
139        }
140
141        /*Find cover art for the current file in the "Cover Art" dir*/
142        NSString *subPath = [[meta path] stringByDeletingPathExtension];
143        NSString *fileName = [subPath lastPathComponent];
144        NSString *ret = [self searchExtForPath:[[[subPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"Cover Art"] stringByAppendingPathComponent:fileName]];
145        if(ret != nil)
146                return ret;
147       
148        /*Find cover art for the current file in the current dir*/
149        ret = [self searchExtForPath:subPath];
150        if(ret != nil)
151                return ret;
152       
153        /*Find cover art for the parent or its parent dir*/
154        ret = [self coverArtForDir:[subPath stringByDeletingLastPathComponent] parents:2];
155        if(ret != nil)
156                return ret;
157       
158        /*Fallback to default*/
159        return [[[NSBundle bundleForClass:[self class]] bundlePath] stringByAppendingString:@"/Contents/Resources/DefaultPreview.png"];
160}
161
162/*!
163 * @brief Override the loading of the cover art method
164 */
165- (void)_loadCoverArt
166{
167        [super _loadCoverArt];
168       
169        /*See if it loaded something*/
170        if([_coverArtLayer texture] != nil)
171                return;
172       
173        /*Get our cover art*/
174        NSString *path = [self coverArtForPath];
175        NSURL *url = [NSURL fileURLWithPath:path];
176        /*Create an image source*/
177        CGImageRef imageRef = CreateImageForURL(url);
178        if(imageRef)
179        {
180                [_coverArtLayer setImage:imageRef];
181                CFRelease(imageRef);
182        }       
183}
184
185/*!
186* @brief populate metadata for TV Shows
187 */
188- (void) populateTVShowMetadataWith:(NSMutableDictionary*)allMeta
189{
190        NSString *value = [allMeta objectForKey:META_TITLE_KEY];
191        if(value != nil)
192        {
193                /*If there is an air date, put it in the title*/
194                NSDate *airDate = [allMeta objectForKey:META_SHOW_AIR_DATE];
195                if(airDate != nil)
196                {
197                        NSDateFormatter *format = [[NSDateFormatter alloc] init];
198                        [format setDateStyle:NSDateFormatterShortStyle];
199                        [format setTimeZone:NSDateFormatterNoStyle];
200                        value = [[format stringFromDate:airDate]stringByAppendingFormat:@" - %@", value];
201                }
202                [_metadataLayer setTitle:value];
203        }
204       
205        /*Get the rating*/
206        value = [allMeta objectForKey:META_RATING_KEY];
207        if(value != nil)
208                [_metadataLayer setRating:value];
209       
210        /*Get the description*/
211        value = [allMeta objectForKey:META_DESCRIPTION_KEY];
212        if(value != nil)
213                if([[SapphireSettings sharedSettings] displaySpoilers])
214                        [_metadataLayer setSummary:value];
215       
216        /*Get the copyright*/
217        value = [allMeta objectForKey:META_COPYRIGHT_KEY];
218        if(value != nil)
219                [_metadataLayer setCopyright:value];
220       
221        /*Get the season and epsiodes*/
222        value = [allMeta objectForKey:META_EPISODE_AND_SEASON_KEY];
223        if(value != nil)
224        {
225                /*Remove the individuals so we don't display them*/
226                [allMeta removeObjectForKey:META_EPISODE_NUMBER_KEY];
227                [allMeta removeObjectForKey:META_SEASON_NUMBER_KEY];
228        }
229       
230}
231
232/*!
233* @brief populate metadata for Movies
234 */
235- (void) populateMovieMetadataWith:(NSMutableDictionary*)allMeta
236{
237        /* Get the movie title */
238        NSString *value=nil;
239        value = [allMeta objectForKey:META_MOVIE_TITLE_KEY];
240        if(value != nil)
241        {
242                /*If there is a release date, put it in the title*/
243                NSDate *releaseDate = [allMeta objectForKey:META_MOVIE_RELEASE_DATE_KEY];
244                if(releaseDate != nil)
245                {
246                        NSDateFormatter *format = [[NSDateFormatter alloc] init];
247                        [format setDateStyle:NSDateFormatterShortStyle];
248                        [format setTimeZone:NSDateFormatterNoStyle];
249                        value = [[format stringFromDate:releaseDate]stringByAppendingFormat:@" - %@", value];
250                        [allMeta removeObjectForKey:META_MOVIE_RELEASE_DATE_KEY];
251                        [allMeta removeObjectForKey:META_MOVIE_TITLE_KEY];
252                }
253                [_metadataLayer setTitle:value];
254        }
255        /*Get the movie plot*/
256        value=nil;
257        value = [allMeta objectForKey:META_MOVIE_PLOT_KEY];
258        if(value != nil)
259                if([[SapphireSettings sharedSettings] displaySpoilers])
260                        [_metadataLayer setSummary:value];
261       
262        NSArray *values=nil;
263        /* Get genres */
264        values=[allMeta objectForKey:META_MOVIE_GENRES_KEY];
265        value=[NSString string];
266        if(values!=nil)
267        {
268                NSEnumerator *valuesEnum = [values objectEnumerator] ;
269                NSString *aValue=nil;
270                while((aValue = [valuesEnum nextObject]) !=nil)
271                {
272                        value=[value stringByAppendingString:[NSString stringWithFormat:@"%@, ",aValue]];
273                }
274                /* get rid of the extra comma */
275                value=[value substringToIndex:[value length]-2];
276                /* sub the array for a formatted string */
277                [allMeta setObject:value forKey:META_MOVIE_GENRES_KEY];
278        }
279        values=nil;
280        values=[allMeta objectForKey:META_MOVIE_DIRECTOR_KEY];
281        value=[NSString string];
282        if(values!=nil)
283        {
284                NSEnumerator *valuesEnum = [values objectEnumerator] ;
285                NSString *aValue=nil;
286                while((aValue = [valuesEnum nextObject]) !=nil)
287                {
288                        value=[value stringByAppendingString:[NSString stringWithFormat:@"%@, ",aValue]];
289                }
290                /* get rid of the extra comma */
291                value=[value substringToIndex:[value length]-2];
292                /* sub the array for a formatted string */
293                [allMeta setObject:value forKey:META_MOVIE_DIRECTOR_KEY];
294        }
295        values=nil;
296        values=[allMeta objectForKey:META_MOVIE_CAST_KEY];
297        value=[NSString string];
298        if(values!=nil)
299        {
300                NSEnumerator *valuesEnum = [values objectEnumerator] ;
301                NSString *aValue=nil;
302                NSString *lastToAdd;
303                if([values count]>2)
304                        lastToAdd=[values objectAtIndex:2] ;
305                while((aValue = [valuesEnum nextObject]) !=nil)
306                {
307                        value=[value stringByAppendingString:[NSString stringWithFormat:@"%@, ",aValue]];
308                        if([aValue isEqualToString:lastToAdd])break;
309                }
310                /* get rid of the extra comma */
311                value=[value substringToIndex:[value length]-2];
312                /* sub the array for a formatted string */
313                [allMeta setObject:value forKey:META_MOVIE_CAST_KEY];
314        }
315}
316
317
318/*!
319 * @brief populate metadata for media files
320 */
321- (void)_populateMetadata
322{
323        [super _populateMetadata];
324        /*See if it loaded anything*/
325        if([[_metadataLayer gimmieMetadataObjs] count])
326                return;
327       
328        /*Get our data then*/
329        NSArray *order = nil;
330        NSMutableDictionary *allMeta = [meta getDisplayedMetaDataInOrder:&order];
331       
332        FileClass fileClass=FILE_CLASS_UNKNOWN ;
333        if([meta isKindOfClass:[SapphireDirectoryMetaData class]])
334                fileClass=FILE_CLASS_NOT_FILE;
335        else
336                fileClass=(FileClass)[meta fileClass];
337               
338       
339       
340        /* TV Show Preview Handeling */
341        if(fileClass==FILE_CLASS_TV_SHOW)
342        {
343                [self  populateTVShowMetadataWith:allMeta];
344        }
345        /* Movie Preview Handeling */
346        else if(fileClass==FILE_CLASS_MOVIE)
347        {
348                [self populateMovieMetadataWith:allMeta];
349        }
350        /* Directory Preview Handeling */
351        else
352        {
353                NSString *value = [allMeta objectForKey:META_TITLE_KEY];
354                if(value != nil)
355                        [_metadataLayer setTitle:value];
356        }
357       
358        NSMutableArray *values = [NSMutableArray array];
359        NSMutableArray *keys = [NSMutableArray array];
360       
361        /*Put the metadata in order*/
362        NSEnumerator *keyEnum = [order objectEnumerator];
363        NSString *key = nil;
364        while((key = [keyEnum nextObject]) != nil)
365        {
366                NSString *value = [allMeta objectForKey:key];
367                if(value != nil)
368                {
369                        [values addObject:value];
370                        [keys addObject:key];
371                }
372        }
373       
374        /*And set it*/
375        [_metadataLayer setMetadata:values withLabels:keys];
376
377}
378
379/*!
380 * @brief Override the info about whether it has metadata
381 *
382 * @return We always have metadata
383 */
384- (BOOL)_assetHasMetadata
385{
386        return YES;
387}
388
389@end
Note: See TracBrowser for help on using the repository browser.