source: trunk/SapphireMetaData.m @ 42

Revision 42, 19.6 KB checked in by gbooker, 7 years ago (diff)

Use tab alignments, makes a much nicer meta-data display.

Line 
1//
2//  SapphireMetaData.m
3//  Sapphire
4//
5//  Created by Graham Booker on 6/22/07.
6//  Copyright 2007 __MyCompanyName__. All rights reserved.
7//
8
9#import "SapphireMetaData.h"
10#import <QTKit/QTKit.h>
11
12//Structure Specific Keys
13#define FILES_KEY                                       @"Files"
14#define DIRS_KEY                                        @"Dirs"
15#define META_VERSION_KEY                        @"Version"
16#define META_VERSION                            1
17
18//File Specific Keys
19#define MODIFIED_KEY                    @"Modified"
20#define WATCHED_KEY                             @"Watched"
21#define FAVORITE_KEY                    @"Favorite"
22#define RESUME_KEY                              @"Resume Time"
23#define SIZE_KEY                                @"Size"
24#define DURATION_KEY                    @"Duration"
25#define AUDIO_DESC_KEY                  @"Audio Description"
26#define SAMPLE_RATE_KEY                 @"Sample Rate"
27#define VIDEO_DESC_KEY                  @"Video Description"
28
29//TV Show Specific Keys
30#define EPISODE_NUMBER_KEY              @"Episode Number"
31#define EPISODE_TITLE_KEY               @"Episode Title"
32#define SEASON_NUMBER_KEY               @"Season"
33#define SHOW_NAME_KEY                   @"Show Name"
34#define SHOW_DESCRIPTION_KEY    @"Show Description"
35#define SHOW_AIR_DATE                   @"Air Date"
36
37
38@implementation NSString (episodeSorting)
39
40// Custom TV Episode handler
41- (NSComparisonResult) episodeCompare:(NSString *)other
42{
43        return [self compare:other options:NSCaseInsensitiveSearch | NSNumericSearch];
44}
45
46@end
47
48@implementation SapphireMetaData
49
50// Static set of file extensions to filter
51static NSArray *extensions = nil;
52
53+(void)load
54{
55        extensions = [[NSArray alloc] initWithObjects:@"avi", @"mov", @"mpg", @"wmv",@"mkv", nil];
56}
57
58- (id)initWithDictionary:(NSDictionary *)dict parent:(SapphireMetaData *)myParent path:(NSString *)myPath
59{
60        self = [super init];
61        if(!self)
62                return nil;
63       
64        else if(dict == nil)
65                metaData = [NSMutableDictionary new];
66        else
67                metaData = [dict mutableCopy];
68        path = [myPath retain];
69        parent = myParent;
70       
71        return self;
72}
73
74- (void)dealloc
75{
76        [metaData release];
77        [path release];
78        [super dealloc];
79}
80
81- (NSMutableDictionary *)dict
82{
83        return metaData;
84}
85
86- (NSString *)path
87{
88        return path;
89}
90
91- (void)setDelegate:(id <SapphireMetaDataDelegate>)newDelegate
92{
93        delegate = newDelegate;
94}
95
96- (void)writeMetaData
97{
98        [parent writeMetaData];
99}
100
101- (void)cancelImport
102{
103}
104
105- (void)resumeImport
106{
107}
108
109- (BOOL)isDirectory:(NSString *)fullPath
110{
111        BOOL isDir = NO;
112        return [[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDir] && isDir;
113}
114
115@end
116
117@implementation SapphireMetaDataCollection
118
119- (id)initWithFile:(NSString *)dictionary path:(NSString *)myPath
120{
121        self = [super init];
122        if(!self)
123                return nil;
124       
125        NSMutableDictionary *mainMetaDictionary = [[NSDictionary dictionaryWithContentsOfFile:dictionary] mutableCopy];
126        if(mainMetaDictionary == nil)
127        {
128                mainMetaDictionary = [[NSMutableDictionary alloc] init];
129        }
130        [mainMetaDictionary setObject:[NSNumber numberWithInt:META_VERSION] forKey:META_VERSION_KEY];
131        self = [self initWithDictionary:mainMetaDictionary parent:nil path:myPath];
132        if(!self)
133                return nil;
134       
135        dictionaryPath = [dictionary retain];
136        mainDirectory = [[SapphireDirectoryMetaData alloc] initWithDictionary:mainMetaDictionary parent:self path:myPath];
137       
138        return self;
139}
140
141- (void)dealloc
142{
143        [mainDirectory release];
144        [dictionaryPath release];
145        [super dealloc];
146}
147
148- (SapphireDirectoryMetaData *)rootDirectory
149{
150        return mainDirectory;
151}
152
153static void makeParentDir(NSFileManager *manager, NSString *dir)
154{
155        NSString *parent = [dir stringByDeletingLastPathComponent];
156       
157        BOOL isDir;
158        if(![manager fileExistsAtPath:parent isDirectory:&isDir])
159                makeParentDir(manager, parent);
160        else if(!isDir)
161                //Can't work with this
162                return;
163       
164        [manager createDirectoryAtPath:dir attributes:nil];
165}
166
167- (void)writeMetaData
168{
169        makeParentDir([NSFileManager defaultManager], [dictionaryPath stringByDeletingLastPathComponent]);
170        [[mainDirectory dict] writeToFile:dictionaryPath atomically:YES];
171}
172
173@end
174
175@interface SapphireDirectoryMetaData (private)
176- (void)reloadDirectoryContents;
177@end
178
179@implementation SapphireDirectoryMetaData
180
181- (id)initWithDictionary:(NSDictionary *)dict parent:(SapphireMetaData *)myParent path:(NSString *)myPath
182{
183        self = [super initWithDictionary:dict parent:myParent path:myPath];
184        if(!self)
185                return nil;
186       
187        metaFiles = [metaData objectForKey:FILES_KEY];
188        if(metaFiles == nil)
189                metaFiles = [NSMutableDictionary dictionary];
190        else
191                metaFiles = [[metaFiles mutableCopy] autorelease];
192        [metaData setObject:metaFiles forKey:FILES_KEY];
193
194        metaDirs = [metaData objectForKey:DIRS_KEY];
195        if(metaDirs == nil)
196                metaDirs = [NSMutableDictionary dictionary];
197        else
198                metaDirs = [[metaDirs mutableCopy] autorelease];
199        [metaData setObject:metaDirs forKey:DIRS_KEY];
200        cachedMetaDirs = [NSMutableDictionary new];
201        cachedMetaFiles = [NSMutableDictionary new];
202       
203        importTimer = nil;
204        [self reloadDirectoryContents];
205        if([self pruneMetaData] || [self updateMetaData])
206                [self writeMetaData];
207       
208        return self;
209}
210
211- (void)dealloc
212{
213        [importTimer invalidate];
214        [importArray release];
215        [cachedMetaDirs release];
216        [cachedMetaFiles release];
217        [files release];
218        [directories release];
219        [super dealloc];
220}
221
222- (void)reloadDirectoryContents
223{
224        [files release];
225        [directories release];
226        files = [NSMutableArray new];
227        directories = [NSMutableArray new];
228       
229        NSArray *names = [[[NSFileManager defaultManager] directoryContentsAtPath:path] retain];
230       
231        NSEnumerator *nameEnum = [names objectEnumerator];
232        NSString *name = nil;
233        // Display Menu Items
234        while((name = [nameEnum nextObject]) != nil)
235        {
236                if([name hasPrefix:@"."])
237                        continue;
238                //Only accept if it is a directory or right extension
239                NSString *extension = [name pathExtension];
240                if([extensions containsObject:extension])
241                        [files addObject:name];
242                else if([self isDirectory:[path stringByAppendingPathComponent:name]])
243                        [directories addObject:name];
244        }
245        [directories sortUsingSelector:@selector(episodeCompare:)];
246        [files sortUsingSelector:@selector(episodeCompare:)];
247}
248
249- (NSArray *)files
250{
251        return files;
252}
253
254- (NSArray *)directories
255{
256        return directories;
257}
258
259- (BOOL)hasPredicatedFiles:(SapphirePredicate *)predicate
260{
261        NSEnumerator *fileEnum = [files objectEnumerator];
262        NSString *file = nil;
263        while((file = [fileEnum nextObject]) != nil)
264        {
265                BOOL include = NO;
266                if([metaFiles objectForKey:file] != nil)
267                {
268                        SapphireFileMetaData *meta = [self metaDataForFile:file];
269                        include = [predicate accept:[meta path] meta:meta];
270                }
271                else
272                        include = [predicate accept:[path stringByAppendingPathComponent:file] meta:nil];
273                if(include)
274                        return YES;
275        }
276        return NO;
277}
278
279- (BOOL)hasPredicatedDirectories:(SapphirePredicate *)predicate
280{
281        NSEnumerator *directoryEnum = [directories objectEnumerator];
282        NSString *directory = nil;
283        while((directory = [directoryEnum nextObject]) != nil)
284        {
285                SapphireDirectoryMetaData *meta = [self metaDataForDirectory:directory];
286                [meta cancelImport];
287               
288                if([meta hasPredicatedFiles:predicate] || [meta hasPredicatedDirectories:predicate])
289                        return YES;
290        }
291        return NO;
292}
293
294- (NSArray *)predicatedFiles:(SapphirePredicate *)predicate
295{
296        NSMutableArray *ret = [NSMutableArray array];
297        NSEnumerator *fileEnum = [files objectEnumerator];
298        NSString *file = nil;
299        while((file = [fileEnum nextObject]) != nil)
300        {
301                BOOL include = NO;
302                if([metaFiles objectForKey:file] != nil)
303                {
304                        SapphireFileMetaData *meta = [self metaDataForFile:file];
305                        include = [predicate accept:[meta path] meta:meta];
306                }
307                else
308                        include = [predicate accept:[path stringByAppendingPathComponent:file] meta:nil];
309                if(include)
310                        [ret addObject:file];
311        }
312        return ret;
313}
314- (NSArray *)predicatedDirectories:(SapphirePredicate *)predicate
315{
316        NSMutableArray *ret = [NSMutableArray array];
317        NSEnumerator *directoryEnum = [directories objectEnumerator];
318        NSString *directory = nil;
319        while((directory = [directoryEnum nextObject]) != nil)
320        {
321                SapphireDirectoryMetaData *meta = [self metaDataForDirectory:directory];
322                [meta cancelImport];
323
324                if([meta hasPredicatedFiles:predicate] || [meta hasPredicatedDirectories:predicate])
325                        [ret addObject:directory];
326        }
327        return ret;
328}
329
330- (SapphireFileMetaData *)metaDataForFile:(NSString *)file
331{
332        SapphireFileMetaData *ret = [cachedMetaFiles objectForKey:file];
333        if(ret == nil)
334        {
335                ret = [[SapphireFileMetaData alloc] initWithDictionary:[metaFiles objectForKey:file] parent:self path:[path stringByAppendingPathComponent:file]];
336                [metaFiles setObject:[ret dict] forKey:file];
337                [cachedMetaFiles setObject:ret forKey:file];
338                [ret autorelease];
339        }
340        return ret;
341}
342
343- (SapphireDirectoryMetaData *)metaDataForDirectory:(NSString *)file
344{
345        SapphireDirectoryMetaData *ret = [cachedMetaDirs objectForKey:file];
346        if(ret == nil)
347        {
348                ret = [[SapphireDirectoryMetaData alloc] initWithDictionary:[metaDirs objectForKey:file] parent:self path:[path stringByAppendingPathComponent:file]];
349                [metaDirs setObject:[ret dict] forKey:file];
350                [cachedMetaDirs setObject:ret forKey:file];
351                [ret autorelease];             
352        }
353        return ret;
354}
355
356- (BOOL)pruneMetaData
357{
358        BOOL ret = NO;
359        NSSet *existingSet = [NSSet setWithArray:files];
360        NSArray *metaArray = [metaFiles allKeys];
361        NSMutableSet *pruneSet = [NSMutableSet setWithArray:metaArray];
362       
363        [pruneSet minusSet:existingSet];
364        if([pruneSet anyObject] != nil)
365        {
366                NSEnumerator *pruneEnum = [pruneSet objectEnumerator];
367                NSString *pruneKey = nil;
368                while((pruneKey = [pruneEnum nextObject]) != nil)
369                        [metaFiles removeObjectForKey:pruneKey];
370                ret = YES;             
371        }
372       
373        existingSet = [NSSet setWithArray:directories];
374        metaArray = [metaDirs allKeys];
375        pruneSet = [NSMutableSet setWithArray:metaArray];
376       
377        [pruneSet minusSet:existingSet];
378        if([pruneSet anyObject] != nil)
379        {
380                NSEnumerator *pruneEnum = [pruneSet objectEnumerator];
381                NSString *pruneKey = nil;
382                while((pruneKey = [pruneEnum nextObject]) != nil)
383                        [metaDirs removeObjectForKey:pruneKey];
384                ret = YES;
385        }
386       
387        return ret;
388}
389
390- (BOOL)updateMetaData
391{
392        BOOL ret = NO;
393        NSArray *metaArray = [metaDirs allKeys];
394        NSSet *metaSet = [NSSet setWithArray:metaArray];
395        NSMutableSet *newSet = [NSMutableSet setWithArray:directories];
396       
397        [newSet minusSet:metaSet];
398        if([newSet anyObject] != nil)
399        {
400                NSEnumerator *newEnum = [newSet objectEnumerator];
401                NSString *newKey = nil;
402                while((newKey = [newEnum nextObject]) != nil)
403                        [metaDirs setObject:[NSMutableDictionary dictionary] forKey:newKey];
404                ret = YES;
405        }
406       
407        NSEnumerator *fileEnum = [files objectEnumerator];
408        NSString *fileName = nil;
409        importArray = [[NSMutableArray alloc] init];
410        while((fileName = [fileEnum nextObject]) != nil)
411        {
412                NSDictionary *fileMeta = [metaFiles objectForKey:fileName];
413                if(fileMeta == nil)
414                        [importArray addObject:fileName];
415                else
416                {
417                        NSString *filePath = [path stringByAppendingPathComponent:fileName];
418                        NSDictionary *props = [[NSFileManager defaultManager] fileAttributesAtPath:filePath traverseLink:YES];
419                        NSDate *modDate = [props objectForKey:NSFileModificationDate];
420                        if([[fileMeta objectForKey:MODIFIED_KEY] intValue] != [modDate timeIntervalSince1970] || [[fileMeta objectForKey:META_VERSION_KEY] intValue] != META_VERSION)
421                                [importArray addObject:fileName];
422                }
423        }
424        return ret;
425}
426
427- (void)processFiles:(NSTimer *)timer
428{
429        NSString *file = [importArray objectAtIndex:0];
430       
431        [[self metaDataForFile:file] updateMetaData];
432       
433        [self writeMetaData];
434        [delegate updateComplete];
435       
436        [importArray removeObjectAtIndex:0];
437        [self resumeImport];
438}
439
440- (void)cancelImport
441{
442        [importTimer invalidate];
443        importTimer = nil;
444}
445
446- (void)resumeImport
447{
448        [importTimer invalidate];
449        if([importArray count])
450                importTimer = [NSTimer scheduledTimerWithTimeInterval:1.1 target:self selector:@selector(processFiles:) userInfo:nil repeats:NO];
451        else
452        {
453                [importTimer invalidate];
454                importTimer = nil;
455                [importArray release];
456                importArray = nil;
457        }
458}
459
460- (SapphireMetaData *)metaDataForSubPath:(NSString *)subPath
461{
462        NSArray *components = [subPath pathComponents];
463        if(![components count])
464                return self;
465        NSString *file = [components objectAtIndex:0];
466       
467        if([self isDirectory:[path stringByAppendingPathComponent:file]])
468        {
469                NSMutableArray *newComp = [components mutableCopy];
470                [newComp removeObjectAtIndex:0];
471                [newComp autorelease];
472                SapphireDirectoryMetaData *nextLevel = [self metaDataForDirectory:file];
473                return [nextLevel metaDataForSubPath:[NSString pathWithComponents:newComp]];
474        }
475        else if([components count] > 1)
476                return nil;
477        return [self metaDataForFile:file];
478}
479
480- (void)processAllFiles
481{
482        NSEnumerator *fileEnum = [files objectEnumerator];
483        NSString *file = nil;
484        while((file = [fileEnum nextObject]) != nil)
485                [[self metaDataForFile:file] updateMetaData];
486}
487
488- (void)scanDirectory
489{
490        NSEnumerator *dirEnum = [directories objectEnumerator];
491        NSString *directory = nil;
492        while((directory = [dirEnum nextObject]) != nil)
493                [[self metaDataForDirectory:directory] scanDirectory];
494}
495
496- (NSArray *)subFileMetas
497{
498        NSMutableArray *ret = [[NSMutableArray alloc] init];
499        NSEnumerator *dirEnum = [directories objectEnumerator];
500        NSString *dir = nil;
501        while((dir = [dirEnum nextObject]) != nil)
502        {
503                SapphireDirectoryMetaData *dirMeta = [self metaDataForDirectory:dir];
504                if(dirMeta != nil)
505                        [ret addObjectsFromArray:[dirMeta subFileMetas]];
506        }
507        NSEnumerator *fileEnum = [files objectEnumerator];
508        NSString *file = nil;
509        while((file = [fileEnum nextObject]) != nil)
510        {
511                SapphireFileMetaData *fileMeta = [self metaDataForFile:file];
512                if(fileMeta != nil)
513                        [ret addObject:fileMeta];
514        }
515        return ret;
516}
517
518- (void)preloadMetaData
519{
520        [self scanDirectory];
521        [self processAllFiles];
522}
523
524- (BOOL)watched
525{
526        NSEnumerator *fileEnum = [files objectEnumerator];
527        NSString *file = nil;
528        while((file = [fileEnum nextObject]) != nil)
529                if(![[self metaDataForFile:file] watched])
530                        return NO;
531
532        NSEnumerator *dirEnum = [directories objectEnumerator];
533        NSString *dir = nil;
534        while((dir = [dirEnum nextObject]) != nil)
535                if(![[self metaDataForDirectory:dir] watched])
536                        return NO;
537
538        return YES;
539}
540
541- (void)setWatched:(BOOL)watched
542{
543        NSEnumerator *dirEnum = [directories objectEnumerator];
544        NSString *dir = nil;
545        while((dir = [dirEnum nextObject]) != nil)
546                [[self metaDataForDirectory:dir] setWatched:watched];
547       
548        NSEnumerator *fileEnum = [files objectEnumerator];
549        NSString *file = nil;
550        while((file = [fileEnum nextObject]) != nil)
551                [[self metaDataForFile:file] setWatched:watched];
552}
553
554- (BOOL)favorite
555{
556        NSEnumerator *fileEnum = [files objectEnumerator];
557        NSString *file = nil;
558        while((file = [fileEnum nextObject]) != nil)
559                if([[self metaDataForFile:file] favorite])
560                        return YES;
561
562        NSEnumerator *dirEnum = [directories objectEnumerator];
563        NSString *dir = nil;
564        while((dir = [dirEnum nextObject]) != nil)
565                if([[self metaDataForDirectory:dir] favorite])
566                        return YES;
567       
568        return NO;
569}
570
571- (void)setFavorite:(BOOL)favorite
572{
573        NSEnumerator *dirEnum = [directories objectEnumerator];
574        NSString *dir = nil;
575        while((dir = [dirEnum nextObject]) != nil)
576                [[self metaDataForDirectory:dir] setFavorite:favorite];
577       
578        NSEnumerator *fileEnum = [files objectEnumerator];
579        NSString *file = nil;
580        while((file = [fileEnum nextObject]) != nil)
581                [[self metaDataForFile:file] setFavorite:favorite];
582}
583
584@end
585
586@implementation SapphireFileMetaData : SapphireMetaData
587
588- (void) updateMetaData
589{
590        NSDictionary *props = [[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES];
591        int modTime = [[props objectForKey:NSFileModificationDate] timeIntervalSince1970];
592       
593        if(props == nil)
594                //No file
595                return;
596       
597        if(modTime != [self modified] || [[metaData objectForKey:META_VERSION_KEY] intValue] != META_VERSION)
598        {
599                NSMutableDictionary *fileMeta = [NSMutableDictionary dictionary];
600               
601                [fileMeta setObject:[NSNumber numberWithInt:modTime] forKey:MODIFIED_KEY];
602                [fileMeta setObject:[props objectForKey:NSFileSize] forKey:SIZE_KEY];
603                [fileMeta setObject:[NSNumber numberWithInt:META_VERSION] forKey:META_VERSION_KEY];
604               
605                NSError *error = nil;
606                QTMovie *movie = [QTMovie movieWithFile:path error:&error];
607                QTTime duration = [movie duration];
608                [fileMeta setObject:[NSNumber numberWithFloat:(float)duration.timeValue/(float)duration.timeScale] forKey:DURATION_KEY];
609                NSArray *audioTracks = [movie tracksOfMediaType:@"soun"];
610                NSNumber *audioSampleRate = nil;
611                if([audioTracks count])
612                {
613                        QTTrack *track = [audioTracks objectAtIndex:0];
614                        QTMedia *media = [track media];
615                        audioSampleRate = [media attributeForKey:QTMediaTimeScaleAttribute];
616                        if(media != nil)
617                        {
618                                Media qtMedia = [media quickTimeMedia];
619                                Handle sampleDesc = NewHandle(1);
620                                GetMediaSampleDescription(qtMedia, 1, (SampleDescriptionHandle)sampleDesc);
621                                CFStringRef userText = nil;
622                                ByteCount       propSize = 0;
623                                QTSoundDescriptionGetProperty((SoundDescriptionHandle)sampleDesc, kQTPropertyClass_SoundDescription, kQTSoundDescriptionPropertyID_UserReadableText, sizeof(userText), &userText, &propSize);
624                                DisposeHandle(sampleDesc);
625                               
626                                if(userText != nil)
627                                {
628                                        [fileMeta setObject:(NSString *)userText forKey:AUDIO_DESC_KEY];
629                                        CFRelease(userText);
630                                }
631                        }
632                }
633                if(audioSampleRate != nil)
634                        [fileMeta setObject:audioSampleRate forKey:SAMPLE_RATE_KEY];
635                NSArray *videoTracks = [movie tracksOfMediaType:@"vide"];
636                if([videoTracks count])
637                {
638                        QTTrack *track = [videoTracks objectAtIndex:0];
639                        QTMedia *media = [track media];
640                        if(media != nil)
641                        {
642                                Media qtMedia = [media quickTimeMedia];
643                                Handle sampleDesc = NewHandle(1);
644                                GetMediaSampleDescription(qtMedia, 1, (SampleDescriptionHandle)sampleDesc);
645                                CFStringRef userText = nil;
646                                ByteCount       propSize = 0;
647                                ICMImageDescriptionGetProperty((ImageDescriptionHandle)sampleDesc, kQTPropertyClass_ImageDescription, kICMImageDescriptionPropertyID_SummaryString, sizeof(userText), &userText, &propSize);
648                                DisposeHandle(sampleDesc);
649                               
650                                if(userText != nil)
651                                {
652                                        [fileMeta setObject:(NSString *)userText forKey:VIDEO_DESC_KEY];
653                                        CFRelease(userText);
654                                }
655                        }
656                }
657                [metaData addEntriesFromDictionary:fileMeta];
658        }
659}
660
661- (int)modified
662{
663        return [[metaData objectForKey:MODIFIED_KEY] intValue];
664}
665
666- (BOOL)watched
667{
668        return [[metaData objectForKey:WATCHED_KEY] boolValue];
669}
670
671- (void)setWatched:(BOOL)watched
672{
673        [metaData setObject:[NSNumber numberWithBool:watched] forKey:WATCHED_KEY];
674}
675
676- (BOOL)favorite
677{
678        return [[metaData objectForKey:FAVORITE_KEY] boolValue];
679}
680
681- (void)setFavorite:(BOOL)favorite
682{
683        [metaData setObject:[NSNumber numberWithBool:favorite] forKey:FAVORITE_KEY];
684}
685
686- (unsigned int)resumeTime
687{
688        return [[metaData objectForKey:RESUME_KEY] unsignedIntValue];
689}
690
691- (void)setResumeTime:(unsigned int)resumeTime
692{
693        [metaData setObject:[NSNumber numberWithUnsignedInt:resumeTime] forKey:RESUME_KEY];
694}
695
696- (long long)size
697{
698        return [[metaData objectForKey:SIZE_KEY] longLongValue];
699}
700
701- (float)duration
702{
703        return [[metaData objectForKey:DURATION_KEY] floatValue];
704}
705
706- (int)sampleRate
707{
708        return [[metaData objectForKey:SAMPLE_RATE_KEY] intValue];
709}
710
711- (NSString *)sizeString
712{
713        float size = [self size];
714        if(size == 0)
715                return @"-";
716        char letter = ' ';
717        if(size >= 1024000)
718        {
719                if(size >= 1024*1024000)
720                {
721                        size /= 1024 * 1024 * 1024;
722                        letter = 'G';
723                }
724                else
725                {
726                        size /= 1024 * 1024;
727                        letter = 'M';
728                }
729        }
730        else if (size >= 1000)
731        {
732                size /= 1024;
733                letter = 'K';
734        }
735        return [NSString stringWithFormat:@"%.1f%cB", size, letter];   
736}
737
738- (NSString *)metaDataDescription
739{
740        NSString *name = [path lastPathComponent];
741        int duration = [self duration];
742        int secs = duration % 60;
743        int mins = (duration /60) % 60;
744        int hours = duration / 3600;
745        NSString *durationStr = nil;
746        if(hours != 0)
747                durationStr = [NSString stringWithFormat:@"%d:%02d:%02d", hours, mins, secs];
748        else if (mins != 0)
749                durationStr = [NSString stringWithFormat:@"%d:%02d", mins, secs];
750        else
751                durationStr = [NSString stringWithFormat:@"%ds", secs];
752        NSMutableString *ret = [NSMutableString stringWithFormat:
753                                                                                                   @"Name: \t%@\n"
754                                                                                                        "Duration: \t%@\n"
755                                                                                                        "Size: \t%@", name, durationStr, [self sizeString]];
756        NSString *videoDesc = [metaData objectForKey:VIDEO_DESC_KEY];
757        if(videoDesc != nil)
758                [ret appendFormat:@"\nVideo: \t%@", videoDesc];
759        NSString *audioDesc = [metaData objectForKey:AUDIO_DESC_KEY];
760        if(audioDesc != nil)
761                [ret appendFormat:@"\nAudio: \t%@", audioDesc];
762        //This aligns the last line correctly.
763        [ret appendString:@"\n "];
764        return ret;
765}
766
767@end
Note: See TracBrowser for help on using the repository browser.