source: trunk/SapphireMetaData.m @ 71

Revision 71, 20.0 KB checked in by gbooker, 7 years ago (diff)

The predicate wasn't actually used, oops.

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