| 436 | | BOOL updateMetaData(SapphireFileMetaData *file) |
| 437 | | { |
| 438 | | BOOL updated =FALSE; |
| 439 | | if([file needsUpdating]) |
| 440 | | { |
| 441 | | /*We did an update*/ |
| 442 | | updated=TRUE ; |
| 443 | | NSMutableDictionary *fileMeta = [NSMutableDictionary dictionary]; |
| 444 | | NSString *path = [file path]; |
| 445 | | NSString *modifiedPath = path; |
| 446 | | NSFileManager *fm = [NSFileManager defaultManager]; |
| | 436 | NSDictionary *fileMetaData(NSString *path, FileContainerType type) |
| | 437 | { |
| | 438 | NSMutableDictionary *fileMeta = [NSMutableDictionary dictionary]; |
| | 439 | NSString *modifiedPath = path; |
| | 440 | NSFileManager *fm = [NSFileManager defaultManager]; |
| | 441 | |
| | 442 | if(type == FILE_CONTAINER_TYPE_VIDEO_TS) |
| | 443 | { |
| | 444 | NSString *vtsPath = [path stringByAppendingPathComponent:@"VIDEO_TS"]; |
| | 445 | NSEnumerator *fileEnum = [[fm directoryContentsAtPath:vtsPath] objectEnumerator]; |
| | 446 | NSString *file; |
| | 447 | while((file = [fileEnum nextObject]) != nil) |
| | 448 | { |
| | 449 | NSString *lowerFile = [file lowercaseString]; |
| | 450 | if([lowerFile hasSuffix:@".ifo"] && ![[lowerFile lastPathComponent] isEqualToString:@"video_ts.ifo"]) |
| | 451 | { |
| | 452 | modifiedPath = [vtsPath stringByAppendingPathComponent:file]; |
| | 453 | break; |
| | 454 | } |
| | 455 | } |
| | 456 | } |
| | 457 | NSDictionary *props = [fm fileAttributesAtPath:modifiedPath traverseLink:YES]; |
| | 458 | int modTime = [[props objectForKey:NSFileModificationDate] timeIntervalSince1970]; |
| | 459 | /*Set modified, size, and version*/ |
| | 460 | [fileMeta setObject:[NSNumber numberWithInt:modTime] forKey:META_FILE_MODIFIED_KEY]; |
| | 461 | [fileMeta setObject:[props objectForKey:NSFileSize] forKey:META_FILE_SIZE_KEY]; |
| | 462 | |
| | 463 | if(type == FILE_CONTAINER_TYPE_QT_MOVIE) |
| | 464 | { |
| | 465 | /*Open the movie*/ |
| | 466 | NSError *error = nil; |
| | 467 | QTMovie *movie = [QTMovie movieWithFile:path error:&error]; |
| | 468 | QTTime duration = [movie duration]; |
| | 469 | [fileMeta setObject:[NSNumber numberWithFloat:(float)duration.timeValue/(float)duration.timeScale] forKey:META_FILE_DURATION_KEY]; |
| | 470 | NSArray *audioTracks = [movie tracksOfMediaType:@"soun"]; |
| | 471 | NSNumber *audioSampleRate = nil; |
| | 472 | int trackCount = [audioTracks count]; |
| | 473 | int i; |
| | 474 | BOOL foundAC3 = NO; |
| | 475 | for(i=0; i<trackCount; i++) |
| | 476 | { |
| | 477 | /*Get the audio track*/ |
| | 478 | QTTrack *track = [audioTracks objectAtIndex:i]; |
| | 479 | QTMedia *media = [track media]; |
| | 480 | if(media != nil) |
| | 481 | { |
| | 482 | /*Get the audio format*/ |
| | 483 | Media qtMedia = [media quickTimeMedia]; |
| | 484 | Handle sampleDesc = NewHandle(1); |
| | 485 | GetMediaSampleDescription(qtMedia, 1, (SampleDescriptionHandle)sampleDesc); |
| | 486 | AudioStreamBasicDescription asbd; |
| | 487 | ByteCount propSize = 0; |
| | 488 | QTSoundDescriptionGetProperty((SoundDescriptionHandle)sampleDesc, kQTPropertyClass_SoundDescription, kQTSoundDescriptionPropertyID_AudioStreamBasicDescription, sizeof(asbd), &asbd, &propSize); |
| | 489 | |
| | 490 | if(propSize != 0 && !foundAC3) |
| | 491 | { |
| | 492 | /*Set the format and sample rate*/ |
| | 493 | NSNumber *format = [NSNumber numberWithUnsignedInt:asbd.mFormatID]; |
| | 494 | [fileMeta setObject:format forKey:META_FILE_AUDIO_FORMAT_KEY]; |
| | 495 | audioSampleRate = [NSNumber numberWithDouble:asbd.mSampleRate]; |
| | 496 | } |
| | 497 | |
| | 498 | CFStringRef userText = nil; |
| | 499 | propSize = 0; |
| | 500 | QTSoundDescriptionGetProperty((SoundDescriptionHandle)sampleDesc, kQTPropertyClass_SoundDescription, kQTSoundDescriptionPropertyID_UserReadableText, sizeof(userText), &userText, &propSize); |
| | 501 | if(userText != nil) |
| | 502 | { |
| | 503 | if([(NSString *)userText hasPrefix:@"AC3"]) |
| | 504 | foundAC3 = YES; |
| | 505 | /*Set the description*/ |
| | 506 | NSString *prevDesc = [fileMeta objectForKey:META_FILE_AUDIO_DESC_KEY]; |
| | 507 | NSString *newDesc; |
| | 508 | if(prevDesc != nil) |
| | 509 | newDesc = [prevDesc stringByAppendingFormat:@"\n%@", userText]; |
| | 510 | else |
| | 511 | newDesc = (NSString *)userText; |
| | 512 | [fileMeta setObject:newDesc forKey:META_FILE_AUDIO_DESC_KEY]; |
| | 513 | CFRelease(userText); |
| | 514 | } |
| | 515 | DisposeHandle(sampleDesc); |
| | 516 | } |
| | 517 | } |
| | 518 | /*Set the sample rate*/ |
| | 519 | if(audioSampleRate != nil) |
| | 520 | [fileMeta setObject:audioSampleRate forKey:META_FILE_SAMPLE_RATE_KEY]; |
| | 521 | NSArray *videoTracks = [movie tracksOfMediaType:@"vide"]; |
| | 522 | trackCount = [videoTracks count]; |
| | 523 | for(i=0; i<trackCount; i++) |
| | 524 | { |
| | 525 | /*Get the video track*/ |
| | 526 | QTTrack *track = [videoTracks objectAtIndex:i]; |
| | 527 | QTMedia *media = [track media]; |
| | 528 | if(media != nil) |
| | 529 | { |
| | 530 | /*Get the video description*/ |
| | 531 | Media qtMedia = [media quickTimeMedia]; |
| | 532 | Handle sampleDesc = NewHandle(1); |
| | 533 | GetMediaSampleDescription(qtMedia, 1, (SampleDescriptionHandle)sampleDesc); |
| | 534 | CFStringRef userText = nil; |
| | 535 | ByteCount propSize = 0; |
| | 536 | ICMImageDescriptionGetProperty((ImageDescriptionHandle)sampleDesc, kQTPropertyClass_ImageDescription, kICMImageDescriptionPropertyID_SummaryString, sizeof(userText), &userText, &propSize); |
| | 537 | DisposeHandle(sampleDesc); |
| | 538 | |
| | 539 | if(userText != nil) |
| | 540 | { |
| | 541 | /*Set the description*/ |
| | 542 | NSString *prevDesc = [fileMeta objectForKey:META_FILE_VIDEO_DESC_KEY]; |
| | 543 | NSString *newDesc; |
| | 544 | if(prevDesc != nil) |
| | 545 | newDesc = [prevDesc stringByAppendingFormat:@"\n%@", userText]; |
| | 546 | else |
| | 547 | newDesc = (NSString *)userText; |
| | 548 | [fileMeta setObject:newDesc forKey:META_FILE_VIDEO_DESC_KEY]; |
| | 549 | CFRelease(userText); |
| | 550 | } |
| | 551 | } |
| | 552 | } |
| | 553 | } //QTMovie |
| | 554 | else if(type == FILE_CONTAINER_TYPE_VIDEO_TS) |
| | 555 | { |
| | 556 | SapphireVideoTsParser *dvd = [[SapphireVideoTsParser alloc] initWithPath:path]; |
| | 557 | id description = [dvd videoFormatsString]; |
| | 558 | if(description) |
| | 559 | [fileMeta setObject:description forKey:META_FILE_VIDEO_DESC_KEY]; |
| | 560 | description = [dvd audioFormatsString]; |
| | 561 | if(description) |
| | 562 | [fileMeta setObject:description forKey:META_FILE_AUDIO_DESC_KEY]; |
| | 563 | description = [dvd mainFeatureDuration]; |
| | 564 | if(description) |
| | 565 | [fileMeta setObject:description forKey:META_FILE_DURATION_KEY]; |
| | 566 | description = [dvd totalSize]; |
| | 567 | if(description) |
| | 568 | [fileMeta setObject:description forKey:META_FILE_SIZE_KEY]; |
| | 569 | description = [dvd subtitlesString]; |
| | 570 | if(description) |
| | 571 | [fileMeta setObject:description forKey:META_FILE_SUBTITLES_KEY ]; |
| 448 | | if([file fileContainerTypeValue] == FILE_CONTAINER_TYPE_VIDEO_TS) |
| 449 | | { |
| 450 | | NSString *vtsPath = [[file path] stringByAppendingPathComponent:@"VIDEO_TS"]; |
| 451 | | NSEnumerator *fileEnum = [[fm directoryContentsAtPath:vtsPath] objectEnumerator]; |
| 452 | | NSString *file; |
| 453 | | while((file = [fileEnum nextObject]) != nil) |
| 454 | | { |
| 455 | | NSString *lowerFile = [file lowercaseString]; |
| 456 | | if([lowerFile hasSuffix:@".ifo"] && ![[lowerFile lastPathComponent] isEqualToString:@"video_ts.ifo"]) |
| 457 | | { |
| 458 | | modifiedPath = [vtsPath stringByAppendingPathComponent:file]; |
| 459 | | break; |
| 460 | | } |
| 461 | | } |
| 462 | | } |
| 463 | | NSDictionary *props = [fm fileAttributesAtPath:modifiedPath traverseLink:YES]; |
| 464 | | int modTime = [[props objectForKey:NSFileModificationDate] timeIntervalSince1970]; |
| 465 | | /*Set modified, size, and version*/ |
| 466 | | [fileMeta setObject:[NSNumber numberWithInt:modTime] forKey:META_FILE_MODIFIED_KEY]; |
| 467 | | [fileMeta setObject:[props objectForKey:NSFileSize] forKey:META_FILE_SIZE_KEY]; |
| 468 | | |
| 469 | | if([file fileContainerTypeValue] == FILE_CONTAINER_TYPE_QT_MOVIE) |
| 470 | | { |
| 471 | | /*Open the movie*/ |
| 472 | | NSError *error = nil; |
| 473 | | QTMovie *movie = [QTMovie movieWithFile:path error:&error]; |
| 474 | | QTTime duration = [movie duration]; |
| 475 | | [fileMeta setObject:[NSNumber numberWithFloat:(float)duration.timeValue/(float)duration.timeScale] forKey:META_FILE_DURATION_KEY]; |
| 476 | | NSArray *audioTracks = [movie tracksOfMediaType:@"soun"]; |
| 477 | | NSNumber *audioSampleRate = nil; |
| 478 | | int trackCount = [audioTracks count]; |
| 479 | | int i; |
| 480 | | BOOL foundAC3 = NO; |
| 481 | | for(i=0; i<trackCount; i++) |
| 482 | | { |
| 483 | | /*Get the audio track*/ |
| 484 | | QTTrack *track = [audioTracks objectAtIndex:i]; |
| 485 | | QTMedia *media = [track media]; |
| 486 | | if(media != nil) |
| 487 | | { |
| 488 | | /*Get the audio format*/ |
| 489 | | Media qtMedia = [media quickTimeMedia]; |
| 490 | | Handle sampleDesc = NewHandle(1); |
| 491 | | GetMediaSampleDescription(qtMedia, 1, (SampleDescriptionHandle)sampleDesc); |
| 492 | | AudioStreamBasicDescription asbd; |
| 493 | | ByteCount propSize = 0; |
| 494 | | QTSoundDescriptionGetProperty((SoundDescriptionHandle)sampleDesc, kQTPropertyClass_SoundDescription, kQTSoundDescriptionPropertyID_AudioStreamBasicDescription, sizeof(asbd), &asbd, &propSize); |
| 495 | | |
| 496 | | if(propSize != 0 && !foundAC3) |
| 497 | | { |
| 498 | | /*Set the format and sample rate*/ |
| 499 | | NSNumber *format = [NSNumber numberWithUnsignedInt:asbd.mFormatID]; |
| 500 | | [fileMeta setObject:format forKey:META_FILE_AUDIO_FORMAT_KEY]; |
| 501 | | audioSampleRate = [NSNumber numberWithDouble:asbd.mSampleRate]; |
| 502 | | } |
| 503 | | |
| 504 | | CFStringRef userText = nil; |
| 505 | | propSize = 0; |
| 506 | | QTSoundDescriptionGetProperty((SoundDescriptionHandle)sampleDesc, kQTPropertyClass_SoundDescription, kQTSoundDescriptionPropertyID_UserReadableText, sizeof(userText), &userText, &propSize); |
| 507 | | if(userText != nil) |
| 508 | | { |
| 509 | | if([(NSString *)userText hasPrefix:@"AC3"]) |
| 510 | | foundAC3 = YES; |
| 511 | | /*Set the description*/ |
| 512 | | NSString *prevDesc = [fileMeta objectForKey:META_FILE_AUDIO_DESC_KEY]; |
| 513 | | NSString *newDesc; |
| 514 | | if(prevDesc != nil) |
| 515 | | newDesc = [prevDesc stringByAppendingFormat:@"\n%@", userText]; |
| 516 | | else |
| 517 | | newDesc = (NSString *)userText; |
| 518 | | [fileMeta setObject:newDesc forKey:META_FILE_AUDIO_DESC_KEY]; |
| 519 | | CFRelease(userText); |
| 520 | | } |
| 521 | | DisposeHandle(sampleDesc); |
| 522 | | } |
| 523 | | } |
| 524 | | /*Set the sample rate*/ |
| 525 | | if(audioSampleRate != nil) |
| 526 | | [fileMeta setObject:audioSampleRate forKey:META_FILE_SAMPLE_RATE_KEY]; |
| 527 | | NSArray *videoTracks = [movie tracksOfMediaType:@"vide"]; |
| 528 | | trackCount = [videoTracks count]; |
| 529 | | for(i=0; i<trackCount; i++) |
| 530 | | { |
| 531 | | /*Get the video track*/ |
| 532 | | QTTrack *track = [videoTracks objectAtIndex:i]; |
| 533 | | QTMedia *media = [track media]; |
| 534 | | if(media != nil) |
| 535 | | { |
| 536 | | /*Get the video description*/ |
| 537 | | Media qtMedia = [media quickTimeMedia]; |
| 538 | | Handle sampleDesc = NewHandle(1); |
| 539 | | GetMediaSampleDescription(qtMedia, 1, (SampleDescriptionHandle)sampleDesc); |
| 540 | | CFStringRef userText = nil; |
| 541 | | ByteCount propSize = 0; |
| 542 | | ICMImageDescriptionGetProperty((ImageDescriptionHandle)sampleDesc, kQTPropertyClass_ImageDescription, kICMImageDescriptionPropertyID_SummaryString, sizeof(userText), &userText, &propSize); |
| 543 | | DisposeHandle(sampleDesc); |
| 544 | | |
| 545 | | if(userText != nil) |
| 546 | | { |
| 547 | | /*Set the description*/ |
| 548 | | NSString *prevDesc = [fileMeta objectForKey:META_FILE_VIDEO_DESC_KEY]; |
| 549 | | NSString *newDesc; |
| 550 | | if(prevDesc != nil) |
| 551 | | newDesc = [prevDesc stringByAppendingFormat:@"\n%@", userText]; |
| 552 | | else |
| 553 | | newDesc = (NSString *)userText; |
| 554 | | [fileMeta setObject:newDesc forKey:META_FILE_VIDEO_DESC_KEY]; |
| 555 | | CFRelease(userText); |
| 556 | | } |
| 557 | | } |
| 558 | | } |
| 559 | | } //QTMovie |
| 560 | | else if([file fileContainerTypeValue] == FILE_CONTAINER_TYPE_VIDEO_TS) |
| 561 | | { |
| 562 | | SapphireVideoTsParser *dvd = [[SapphireVideoTsParser alloc] initWithPath:path]; |
| 563 | | id description = [dvd videoFormatsString]; |
| 564 | | if(description) |
| 565 | | [fileMeta setObject:description forKey:META_FILE_VIDEO_DESC_KEY]; |
| 566 | | description = [dvd audioFormatsString]; |
| 567 | | if(description) |
| 568 | | [fileMeta setObject:description forKey:META_FILE_AUDIO_DESC_KEY]; |
| 569 | | description = [dvd mainFeatureDuration]; |
| 570 | | if(description) |
| 571 | | [fileMeta setObject:description forKey:META_FILE_DURATION_KEY]; |
| 572 | | description = [dvd totalSize]; |
| 573 | | if(description) |
| 574 | | [fileMeta setObject:description forKey:META_FILE_SIZE_KEY]; |
| 575 | | description = [dvd subtitlesString]; |
| 576 | | if(description) |
| 577 | | [fileMeta setObject:description forKey:META_FILE_SUBTITLES_KEY ]; |
| 578 | | |
| 579 | | [dvd release]; |
| 580 | | } // VIDEO_TS |
| 581 | | [file addFileData:fileMeta]; |
| 582 | | } |
| 583 | | return updated; |
| | 573 | [dvd release]; |
| | 574 | } // VIDEO_TS |
| | 575 | return fileMeta; |