From 9652caa8bb33fb6e2438ede5dbd3cad9f5be2fed Mon Sep 17 00:00:00 2001 From: Vincent <550862452@qq.com> Date: Thu, 31 Dec 2015 17:51:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加缓存 --- src/DOUAudioFile.h | 4 +- src/DOUAudioFileProvider.m | 900 +++++++++++++++++++------------------ 2 files changed, 460 insertions(+), 444 deletions(-) diff --git a/src/DOUAudioFile.h b/src/DOUAudioFile.h index b5ddb4d..af00eba 100644 --- a/src/DOUAudioFile.h +++ b/src/DOUAudioFile.h @@ -20,9 +20,11 @@ @protocol DOUAudioFile +@property (nonatomic,strong) NSURL *audioFileURL; + @required -- (NSURL *)audioFileURL; +//- (NSURL *)audioFileURL; @optional diff --git a/src/DOUAudioFileProvider.m b/src/DOUAudioFileProvider.m index 33fa16f..5bb3a3f 100644 --- a/src/DOUAudioFileProvider.m +++ b/src/DOUAudioFileProvider.m @@ -37,17 +37,17 @@ @interface DOUAudioFileProvider () { @protected - id _audioFile; - DOUAudioFileProviderEventBlock _eventBlock; - NSString *_cachedPath; - NSURL *_cachedURL; - NSString *_mimeType; - NSString *_fileExtension; - NSString *_sha256; - NSData *_mappedData; - NSUInteger _expectedLength; - NSUInteger _receivedLength; - BOOL _failed; + id _audioFile; + DOUAudioFileProviderEventBlock _eventBlock; + NSString *_cachedPath; + NSURL *_cachedURL; + NSString *_mimeType; + NSString *_fileExtension; + NSString *_sha256; + NSData *_mappedData; + NSUInteger _expectedLength; + NSUInteger _receivedLength; + BOOL _failed; } - (instancetype)_initWithAudioFile:(id )audioFile; @@ -59,23 +59,23 @@ @interface _DOUAudioLocalFileProvider : DOUAudioFileProvider @interface _DOUAudioRemoteFileProvider : DOUAudioFileProvider { @private - DOUSimpleHTTPRequest *_request; - NSURL *_audioFileURL; - - CC_SHA256_CTX *_sha256Ctx; - - AudioFileStreamID _audioFileStreamID; - BOOL _requiresCompleteFile; - BOOL _readyToProducePackets; - BOOL _requestCompleted; + DOUSimpleHTTPRequest *_request; + NSURL *_audioFileURL; + + CC_SHA256_CTX *_sha256Ctx; + + AudioFileStreamID _audioFileStreamID; + BOOL _requiresCompleteFile; + BOOL _readyToProducePackets; + BOOL _requestCompleted; } @end #if TARGET_OS_IPHONE @interface _DOUAudioMediaLibraryFileProvider : DOUAudioFileProvider { @private - DOUMPMediaLibraryAssetLoader *_assetLoader; - BOOL _loaderCompleted; + DOUMPMediaLibraryAssetLoader *_assetLoader; + BOOL _loaderCompleted; } @end #endif /* TARGET_OS_IPHONE */ @@ -86,81 +86,81 @@ @implementation _DOUAudioLocalFileProvider - (instancetype)_initWithAudioFile:(id )audioFile { - self = [super _initWithAudioFile:audioFile]; - if (self) { - _cachedURL = [audioFile audioFileURL]; - _cachedPath = [_cachedURL path]; - - BOOL isDirectory = NO; - if (![[NSFileManager defaultManager] fileExistsAtPath:_cachedPath - isDirectory:&isDirectory] || - isDirectory) { - return nil; + self = [super _initWithAudioFile:audioFile]; + if (self) { + _cachedURL = [audioFile audioFileURL]; + _cachedPath = [_cachedURL path]; + + BOOL isDirectory = NO; + if (![[NSFileManager defaultManager] fileExistsAtPath:_cachedPath + isDirectory:&isDirectory] || + isDirectory) { + return nil; + } + + _mappedData = [NSData dou_dataWithMappedContentsOfFile:_cachedPath]; + _expectedLength = [_mappedData length]; + _receivedLength = [_mappedData length]; } - - _mappedData = [NSData dou_dataWithMappedContentsOfFile:_cachedPath]; - _expectedLength = [_mappedData length]; - _receivedLength = [_mappedData length]; - } - - return self; + + return self; } - (NSString *)mimeType { - if (_mimeType == nil && - [self fileExtension] != nil) { - CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[self fileExtension], NULL); - if (uti != NULL) { - _mimeType = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)); - CFRelease(uti); + if (_mimeType == nil && + [self fileExtension] != nil) { + CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[self fileExtension], NULL); + if (uti != NULL) { + _mimeType = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)); + CFRelease(uti); + } } - } - - return _mimeType; + + return _mimeType; } - (NSString *)fileExtension { - if (_fileExtension == nil) { - _fileExtension = [[[self audioFile] audioFileURL] pathExtension]; - } - - return _fileExtension; + if (_fileExtension == nil) { + _fileExtension = [[[self audioFile] audioFileURL] pathExtension]; + } + + return _fileExtension; } - (NSString *)sha256 { - if (_sha256 == nil && - [DOUAudioStreamer options] & DOUAudioStreamerRequireSHA256 && - [self mappedData] != nil) { - unsigned char hash[CC_SHA256_DIGEST_LENGTH]; - CC_SHA256([[self mappedData] bytes], (CC_LONG)[[self mappedData] length], hash); - - NSMutableString *result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; - for (size_t i = 0; i < CC_SHA256_DIGEST_LENGTH; ++i) { - [result appendFormat:@"%02x", hash[i]]; + if (_sha256 == nil && + [DOUAudioStreamer options] & DOUAudioStreamerRequireSHA256 && + [self mappedData] != nil) { + unsigned char hash[CC_SHA256_DIGEST_LENGTH]; + CC_SHA256([[self mappedData] bytes], (CC_LONG)[[self mappedData] length], hash); + + NSMutableString *result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; + for (size_t i = 0; i < CC_SHA256_DIGEST_LENGTH; ++i) { + [result appendFormat:@"%02x", hash[i]]; + } + + _sha256 = [result copy]; } - - _sha256 = [result copy]; - } - - return _sha256; + + return _sha256; } - (NSUInteger)downloadSpeed { - return _receivedLength; + return _receivedLength; } - (BOOL)isReady { - return YES; + return YES; } - (BOOL)isFinished { - return YES; + return YES; } @end @@ -173,208 +173,212 @@ @implementation _DOUAudioRemoteFileProvider - (instancetype)_initWithAudioFile:(id )audioFile { - self = [super _initWithAudioFile:audioFile]; - if (self) { - _audioFileURL = [audioFile audioFileURL]; - - if ([DOUAudioStreamer options] & DOUAudioStreamerRequireSHA256) { - _sha256Ctx = (CC_SHA256_CTX *)malloc(sizeof(CC_SHA256_CTX)); - CC_SHA256_Init(_sha256Ctx); + self = [super _initWithAudioFile:audioFile]; + if (self) { + _audioFileURL = [audioFile audioFileURL]; + + if ([DOUAudioStreamer options] & DOUAudioStreamerRequireSHA256) { + _sha256Ctx = (CC_SHA256_CTX *)malloc(sizeof(CC_SHA256_CTX)); + CC_SHA256_Init(_sha256Ctx); + } + + [self _openAudioFileStream]; + [self _createRequest]; + [_request start]; } - - [self _openAudioFileStream]; - [self _createRequest]; - [_request start]; - } - - return self; + + return self; } - (void)dealloc { - @synchronized(_request) { - [_request setCompletedBlock:NULL]; - [_request setProgressBlock:NULL]; - [_request setDidReceiveResponseBlock:NULL]; - [_request setDidReceiveDataBlock:NULL]; - - [_request cancel]; - } - - if (_sha256Ctx != NULL) { - free(_sha256Ctx); - } - - [self _closeAudioFileStream]; - - if ([DOUAudioStreamer options] & DOUAudioStreamerRemoveCacheOnDeallocation) { - [[NSFileManager defaultManager] removeItemAtPath:_cachedPath error:NULL]; - } + @synchronized(_request) { + [_request setCompletedBlock:NULL]; + [_request setProgressBlock:NULL]; + [_request setDidReceiveResponseBlock:NULL]; + [_request setDidReceiveDataBlock:NULL]; + + [_request cancel]; + } + + if (_sha256Ctx != NULL) { + free(_sha256Ctx); + } + + [self _closeAudioFileStream]; + + if ([DOUAudioStreamer options] & DOUAudioStreamerRemoveCacheOnDeallocation) { + [[NSFileManager defaultManager] removeItemAtPath:_cachedPath error:NULL]; + } } + (NSString *)_sha256ForAudioFileURL:(NSURL *)audioFileURL { - NSString *string = [audioFileURL absoluteString]; - unsigned char hash[CC_SHA256_DIGEST_LENGTH]; - CC_SHA256([string UTF8String], (CC_LONG)[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding], hash); - - NSMutableString *result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; - for (size_t i = 0; i < CC_SHA256_DIGEST_LENGTH; ++i) { - [result appendFormat:@"%02x", hash[i]]; - } - - return result; + NSString *string = [audioFileURL absoluteString]; + unsigned char hash[CC_SHA256_DIGEST_LENGTH]; + CC_SHA256([string UTF8String], (CC_LONG)[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding], hash); + + NSMutableString *result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; + for (size_t i = 0; i < CC_SHA256_DIGEST_LENGTH; ++i) { + [result appendFormat:@"%02x", hash[i]]; + } + + return result; } + (NSString *)_cachedPathForAudioFileURL:(NSURL *)audioFileURL { - NSString *filename = [NSString stringWithFormat:@"douas-%@.tmp", [self _sha256ForAudioFileURL:audioFileURL]]; - return [NSTemporaryDirectory() stringByAppendingPathComponent:filename]; + NSString *filename = [NSString stringWithFormat:@"douas-%@.tmp", [self _sha256ForAudioFileURL:audioFileURL]]; + return [NSTemporaryDirectory() stringByAppendingPathComponent:filename]; } - (void)_invokeEventBlock { - if (_eventBlock != NULL) { - _eventBlock(); - } + if (_eventBlock != NULL) { + _eventBlock(); + } } - (void)_requestDidComplete { - if ([_request isFailed] || - !([_request statusCode] >= 200 && [_request statusCode] < 300)) { - _failed = YES; - } - else { - _requestCompleted = YES; - [_mappedData dou_synchronizeMappedFile]; - } - - if (!_failed && - _sha256Ctx != NULL) { - unsigned char hash[CC_SHA256_DIGEST_LENGTH]; - CC_SHA256_Final(hash, _sha256Ctx); - - NSMutableString *result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; - for (size_t i = 0; i < CC_SHA256_DIGEST_LENGTH; ++i) { - [result appendFormat:@"%02x", hash[i]]; + if ([_request isFailed] || + !([_request statusCode] >= 200 && [_request statusCode] < 300)) { + _failed = YES; } - - _sha256 = [result copy]; - } - - if (gHintFile != nil && - gHintProvider == nil) { - gHintProvider = [[[self class] alloc] _initWithAudioFile:gHintFile]; - } - - [self _invokeEventBlock]; + else { + _requestCompleted = YES; + [_mappedData dou_synchronizeMappedFile]; + + [[NSFileManager defaultManager] moveItemAtPath:self.cachedPath toPath:[self.cachedPath stringByDeletingPathExtension] error:nil]; + + + } + + if (!_failed && + _sha256Ctx != NULL) { + unsigned char hash[CC_SHA256_DIGEST_LENGTH]; + CC_SHA256_Final(hash, _sha256Ctx); + + NSMutableString *result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; + for (size_t i = 0; i < CC_SHA256_DIGEST_LENGTH; ++i) { + [result appendFormat:@"%02x", hash[i]]; + } + + _sha256 = [result copy]; + } + + if (gHintFile != nil && + gHintProvider == nil) { + gHintProvider = [[[self class] alloc] _initWithAudioFile:gHintFile]; + } + + [self _invokeEventBlock]; } - (void)_requestDidReportProgress:(double)progress { - [self _invokeEventBlock]; + [self _invokeEventBlock]; } - (void)_requestDidReceiveResponse { - _expectedLength = [_request responseContentLength]; - - _cachedPath = [[self class] _cachedPathForAudioFileURL:_audioFileURL]; - _cachedURL = [NSURL fileURLWithPath:_cachedPath]; - - [[NSFileManager defaultManager] createFileAtPath:_cachedPath contents:nil attributes:nil]; - [[NSFileHandle fileHandleForWritingAtPath:_cachedPath] truncateFileAtOffset:_expectedLength]; - - _mimeType = [[_request responseHeaders] objectForKey:@"Content-Type"]; - - _mappedData = [NSData dou_modifiableDataWithMappedContentsOfFile:_cachedPath]; + _expectedLength = [_request responseContentLength]; + + _cachedPath = [[self class] _cachedPathForAudioFileURL:_audioFileURL]; + _cachedURL = [NSURL fileURLWithPath:_cachedPath]; + + [[NSFileManager defaultManager] createFileAtPath:_cachedPath contents:nil attributes:nil]; + [[NSFileHandle fileHandleForWritingAtPath:_cachedPath] truncateFileAtOffset:_expectedLength]; + + _mimeType = [[_request responseHeaders] objectForKey:@"Content-Type"]; + + _mappedData = [NSData dou_modifiableDataWithMappedContentsOfFile:_cachedPath]; } - (void)_requestDidReceiveData:(NSData *)data { - if (_mappedData == nil) { - return; - } - - NSUInteger availableSpace = _expectedLength - _receivedLength; - NSUInteger bytesToWrite = MIN(availableSpace, [data length]); - - memcpy((uint8_t *)[_mappedData bytes] + _receivedLength, [data bytes], bytesToWrite); - _receivedLength += bytesToWrite; - - if (_sha256Ctx != NULL) { - CC_SHA256_Update(_sha256Ctx, [data bytes], (CC_LONG)[data length]); - } - - if (!_readyToProducePackets && !_failed && !_requiresCompleteFile) { - OSStatus status = kAudioFileStreamError_UnsupportedFileType; - - if (_audioFileStreamID != NULL) { - status = AudioFileStreamParseBytes(_audioFileStreamID, - (UInt32)[data length], - [data bytes], - 0); + if (_mappedData == nil) { + return; } - - if (status != noErr && status != kAudioFileStreamError_NotOptimized) { - NSArray *fallbackTypeIDs = [self _fallbackTypeIDs]; - for (NSNumber *typeIDNumber in fallbackTypeIDs) { - AudioFileTypeID typeID = (AudioFileTypeID)[typeIDNumber unsignedLongValue]; - [self _closeAudioFileStream]; - [self _openAudioFileStreamWithFileTypeHint:typeID]; - + + NSUInteger availableSpace = _expectedLength - _receivedLength; + NSUInteger bytesToWrite = MIN(availableSpace, [data length]); + + memcpy((uint8_t *)[_mappedData bytes] + _receivedLength, [data bytes], bytesToWrite); + _receivedLength += bytesToWrite; + + if (_sha256Ctx != NULL) { + CC_SHA256_Update(_sha256Ctx, [data bytes], (CC_LONG)[data length]); + } + + if (!_readyToProducePackets && !_failed && !_requiresCompleteFile) { + OSStatus status = kAudioFileStreamError_UnsupportedFileType; + if (_audioFileStreamID != NULL) { - status = AudioFileStreamParseBytes(_audioFileStreamID, - (UInt32)_receivedLength, - [_mappedData bytes], - 0); - - if (status == noErr || status == kAudioFileStreamError_NotOptimized) { - break; - } + status = AudioFileStreamParseBytes(_audioFileStreamID, + (UInt32)[data length], + [data bytes], + 0); + } + + if (status != noErr && status != kAudioFileStreamError_NotOptimized) { + NSArray *fallbackTypeIDs = [self _fallbackTypeIDs]; + for (NSNumber *typeIDNumber in fallbackTypeIDs) { + AudioFileTypeID typeID = (AudioFileTypeID)[typeIDNumber unsignedLongValue]; + [self _closeAudioFileStream]; + [self _openAudioFileStreamWithFileTypeHint:typeID]; + + if (_audioFileStreamID != NULL) { + status = AudioFileStreamParseBytes(_audioFileStreamID, + (UInt32)_receivedLength, + [_mappedData bytes], + 0); + + if (status == noErr || status == kAudioFileStreamError_NotOptimized) { + break; + } + } + } + + if (status != noErr && status != kAudioFileStreamError_NotOptimized) { + _failed = YES; + } + } + + if (status == kAudioFileStreamError_NotOptimized) { + [self _closeAudioFileStream]; + _requiresCompleteFile = YES; } - } - - if (status != noErr && status != kAudioFileStreamError_NotOptimized) { - _failed = YES; - } - } - - if (status == kAudioFileStreamError_NotOptimized) { - [self _closeAudioFileStream]; - _requiresCompleteFile = YES; } - } } - (void)_createRequest { - _request = [DOUSimpleHTTPRequest requestWithURL:_audioFileURL]; - __unsafe_unretained _DOUAudioRemoteFileProvider *_self = self; - - [_request setCompletedBlock:^{ - [_self _requestDidComplete]; - }]; - - [_request setProgressBlock:^(double downloadProgress) { - [_self _requestDidReportProgress:downloadProgress]; - }]; - - [_request setDidReceiveResponseBlock:^{ - [_self _requestDidReceiveResponse]; - }]; - - [_request setDidReceiveDataBlock:^(NSData *data) { - [_self _requestDidReceiveData:data]; - }]; + _request = [DOUSimpleHTTPRequest requestWithURL:_audioFileURL]; + __unsafe_unretained _DOUAudioRemoteFileProvider *_self = self; + + [_request setCompletedBlock:^{ + [_self _requestDidComplete]; + }]; + + [_request setProgressBlock:^(double downloadProgress) { + [_self _requestDidReportProgress:downloadProgress]; + }]; + + [_request setDidReceiveResponseBlock:^{ + [_self _requestDidReceiveResponse]; + }]; + + [_request setDidReceiveDataBlock:^(NSData *data) { + [_self _requestDidReceiveData:data]; + }]; } - (void)_handleAudioFileStreamProperty:(AudioFileStreamPropertyID)propertyID { - if (propertyID == kAudioFileStreamProperty_ReadyToProducePackets) { - _readyToProducePackets = YES; - } + if (propertyID == kAudioFileStreamProperty_ReadyToProducePackets) { + _readyToProducePackets = YES; + } } - (void)_handleAudioFileStreamPackets:(const void *)packets @@ -385,12 +389,12 @@ - (void)_handleAudioFileStreamPackets:(const void *)packets } static void audio_file_stream_property_listener_proc(void *inClientData, - AudioFileStreamID inAudioFileStream, - AudioFileStreamPropertyID inPropertyID, - UInt32 *ioFlags) + AudioFileStreamID inAudioFileStream, + AudioFileStreamPropertyID inPropertyID, + UInt32 *ioFlags) { - __unsafe_unretained _DOUAudioRemoteFileProvider *fileProvider = (__bridge _DOUAudioRemoteFileProvider *)inClientData; - [fileProvider _handleAudioFileStreamProperty:inPropertyID]; + __unsafe_unretained _DOUAudioRemoteFileProvider *fileProvider = (__bridge _DOUAudioRemoteFileProvider *)inClientData; + [fileProvider _handleAudioFileStreamProperty:inPropertyID]; } static void audio_file_stream_packets_proc(void *inClientData, @@ -399,123 +403,123 @@ static void audio_file_stream_packets_proc(void *inClientData, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions) { - __unsafe_unretained _DOUAudioRemoteFileProvider *fileProvider = (__bridge _DOUAudioRemoteFileProvider *)inClientData; - [fileProvider _handleAudioFileStreamPackets:inInputData - numberOfBytes:inNumberBytes - numberOfPackets:inNumberPackets - packetDescriptions:inPacketDescriptions]; + __unsafe_unretained _DOUAudioRemoteFileProvider *fileProvider = (__bridge _DOUAudioRemoteFileProvider *)inClientData; + [fileProvider _handleAudioFileStreamPackets:inInputData + numberOfBytes:inNumberBytes + numberOfPackets:inNumberPackets + packetDescriptions:inPacketDescriptions]; } - (void)_openAudioFileStream { - [self _openAudioFileStreamWithFileTypeHint:0]; + [self _openAudioFileStreamWithFileTypeHint:0]; } - (void)_openAudioFileStreamWithFileTypeHint:(AudioFileTypeID)fileTypeHint { - OSStatus status = AudioFileStreamOpen((__bridge void *)self, - audio_file_stream_property_listener_proc, - audio_file_stream_packets_proc, - fileTypeHint, - &_audioFileStreamID); - - if (status != noErr) { - _audioFileStreamID = NULL; - } + OSStatus status = AudioFileStreamOpen((__bridge void *)self, + audio_file_stream_property_listener_proc, + audio_file_stream_packets_proc, + fileTypeHint, + &_audioFileStreamID); + + if (status != noErr) { + _audioFileStreamID = NULL; + } } - (void)_closeAudioFileStream { - if (_audioFileStreamID != NULL) { - AudioFileStreamClose(_audioFileStreamID); - _audioFileStreamID = NULL; - } + if (_audioFileStreamID != NULL) { + AudioFileStreamClose(_audioFileStreamID); + _audioFileStreamID = NULL; + } } - (NSArray *)_fallbackTypeIDs { - NSMutableArray *fallbackTypeIDs = [NSMutableArray array]; - NSMutableSet *fallbackTypeIDSet = [NSMutableSet set]; - - struct { - CFStringRef specifier; - AudioFilePropertyID propertyID; - } properties[] = { - { (__bridge CFStringRef)[self mimeType], kAudioFileGlobalInfo_TypesForMIMEType }, - { (__bridge CFStringRef)[self fileExtension], kAudioFileGlobalInfo_TypesForExtension } - }; - - const size_t numberOfProperties = sizeof(properties) / sizeof(properties[0]); - - for (size_t i = 0; i < numberOfProperties; ++i) { - if (properties[i].specifier == NULL) { - continue; - } - - UInt32 outSize = 0; - OSStatus status; - - status = AudioFileGetGlobalInfoSize(properties[i].propertyID, + NSMutableArray *fallbackTypeIDs = [NSMutableArray array]; + NSMutableSet *fallbackTypeIDSet = [NSMutableSet set]; + + struct { + CFStringRef specifier; + AudioFilePropertyID propertyID; + } properties[] = { + { (__bridge CFStringRef)[self mimeType], kAudioFileGlobalInfo_TypesForMIMEType }, + { (__bridge CFStringRef)[self fileExtension], kAudioFileGlobalInfo_TypesForExtension } + }; + + const size_t numberOfProperties = sizeof(properties) / sizeof(properties[0]); + + for (size_t i = 0; i < numberOfProperties; ++i) { + if (properties[i].specifier == NULL) { + continue; + } + + UInt32 outSize = 0; + OSStatus status; + + status = AudioFileGetGlobalInfoSize(properties[i].propertyID, + sizeof(properties[i].specifier), + &properties[i].specifier, + &outSize); + if (status != noErr) { + continue; + } + + size_t count = outSize / sizeof(AudioFileTypeID); + AudioFileTypeID *buffer = (AudioFileTypeID *)malloc(outSize); + if (buffer == NULL) { + continue; + } + + status = AudioFileGetGlobalInfo(properties[i].propertyID, sizeof(properties[i].specifier), &properties[i].specifier, - &outSize); - if (status != noErr) { - continue; - } - - size_t count = outSize / sizeof(AudioFileTypeID); - AudioFileTypeID *buffer = (AudioFileTypeID *)malloc(outSize); - if (buffer == NULL) { - continue; - } - - status = AudioFileGetGlobalInfo(properties[i].propertyID, - sizeof(properties[i].specifier), - &properties[i].specifier, - &outSize, - buffer); - if (status != noErr) { - free(buffer); - continue; - } - - for (size_t j = 0; j < count; ++j) { - NSNumber *tid = [NSNumber numberWithUnsignedLong:buffer[j]]; - if ([fallbackTypeIDSet containsObject:tid]) { - continue; - } - - [fallbackTypeIDs addObject:tid]; - [fallbackTypeIDSet addObject:tid]; + &outSize, + buffer); + if (status != noErr) { + free(buffer); + continue; + } + + for (size_t j = 0; j < count; ++j) { + NSNumber *tid = [NSNumber numberWithUnsignedLong:buffer[j]]; + if ([fallbackTypeIDSet containsObject:tid]) { + continue; + } + + [fallbackTypeIDs addObject:tid]; + [fallbackTypeIDSet addObject:tid]; + } + + free(buffer); } - - free(buffer); - } - - return fallbackTypeIDs; + + return fallbackTypeIDs; } - (NSString *)fileExtension { - if (_fileExtension == nil) { - _fileExtension = [[[[self audioFile] audioFileURL] path] pathExtension]; - } - - return _fileExtension; + if (_fileExtension == nil) { + _fileExtension = [[[[self audioFile] audioFileURL] path] pathExtension]; + } + + return _fileExtension; } - (NSUInteger)downloadSpeed { - return [_request downloadSpeed]; + return [_request downloadSpeed]; } - (BOOL)isReady { - if (!_requiresCompleteFile) { - return _readyToProducePackets; - } - - return _requestCompleted; + if (!_requiresCompleteFile) { + return _readyToProducePackets; + } + + return _requestCompleted; } @end @@ -527,98 +531,98 @@ @implementation _DOUAudioMediaLibraryFileProvider - (instancetype)_initWithAudioFile:(id )audioFile { - self = [super _initWithAudioFile:audioFile]; - if (self) { - [self _createAssetLoader]; - [_assetLoader start]; - } - - return self; + self = [super _initWithAudioFile:audioFile]; + if (self) { + [self _createAssetLoader]; + [_assetLoader start]; + } + + return self; } - (void)dealloc { - @synchronized(_assetLoader) { - [_assetLoader setCompletedBlock:NULL]; - [_assetLoader cancel]; - } - - [[NSFileManager defaultManager] removeItemAtPath:[_assetLoader cachedPath] - error:NULL]; + @synchronized(_assetLoader) { + [_assetLoader setCompletedBlock:NULL]; + [_assetLoader cancel]; + } + + [[NSFileManager defaultManager] removeItemAtPath:[_assetLoader cachedPath] + error:NULL]; } - (void)_invokeEventBlock { - if (_eventBlock != NULL) { - _eventBlock(); - } + if (_eventBlock != NULL) { + _eventBlock(); + } } - (void)_assetLoaderDidComplete { - if ([_assetLoader isFailed]) { - _failed = YES; + if ([_assetLoader isFailed]) { + _failed = YES; + [self _invokeEventBlock]; + return; + } + + _mimeType = [_assetLoader mimeType]; + _fileExtension = [_assetLoader fileExtension]; + + _cachedPath = [_assetLoader cachedPath]; + _cachedURL = [NSURL fileURLWithPath:_cachedPath]; + + _mappedData = [NSData dou_dataWithMappedContentsOfFile:_cachedPath]; + _expectedLength = [_mappedData length]; + _receivedLength = [_mappedData length]; + + _loaderCompleted = YES; [self _invokeEventBlock]; - return; - } - - _mimeType = [_assetLoader mimeType]; - _fileExtension = [_assetLoader fileExtension]; - - _cachedPath = [_assetLoader cachedPath]; - _cachedURL = [NSURL fileURLWithPath:_cachedPath]; - - _mappedData = [NSData dou_dataWithMappedContentsOfFile:_cachedPath]; - _expectedLength = [_mappedData length]; - _receivedLength = [_mappedData length]; - - _loaderCompleted = YES; - [self _invokeEventBlock]; } - (void)_createAssetLoader { - _assetLoader = [DOUMPMediaLibraryAssetLoader loaderWithURL:[_audioFile audioFileURL]]; - - __weak typeof(self) weakSelf = self; - [_assetLoader setCompletedBlock:^{ - __strong typeof(weakSelf) strongSelf = weakSelf; - [strongSelf _assetLoaderDidComplete]; - }]; + _assetLoader = [DOUMPMediaLibraryAssetLoader loaderWithURL:[_audioFile audioFileURL]]; + + __weak typeof(self) weakSelf = self; + [_assetLoader setCompletedBlock:^{ + __strong typeof(weakSelf) strongSelf = weakSelf; + [strongSelf _assetLoaderDidComplete]; + }]; } - (NSString *)sha256 { - if (_sha256 == nil && - [DOUAudioStreamer options] & DOUAudioStreamerRequireSHA256 && - [self mappedData] != nil) { - unsigned char hash[CC_SHA256_DIGEST_LENGTH]; - CC_SHA256([[self mappedData] bytes], (CC_LONG)[[self mappedData] length], hash); - - NSMutableString *result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; - for (size_t i = 0; i < CC_SHA256_DIGEST_LENGTH; ++i) { - [result appendFormat:@"%02x", hash[i]]; + if (_sha256 == nil && + [DOUAudioStreamer options] & DOUAudioStreamerRequireSHA256 && + [self mappedData] != nil) { + unsigned char hash[CC_SHA256_DIGEST_LENGTH]; + CC_SHA256([[self mappedData] bytes], (CC_LONG)[[self mappedData] length], hash); + + NSMutableString *result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; + for (size_t i = 0; i < CC_SHA256_DIGEST_LENGTH; ++i) { + [result appendFormat:@"%02x", hash[i]]; + } + + _sha256 = [result copy]; } - - _sha256 = [result copy]; - } - - return _sha256; + + return _sha256; } - (NSUInteger)downloadSpeed { - return _receivedLength; + return _receivedLength; } - (BOOL)isReady { - return _loaderCompleted; + return _loaderCompleted; } - (BOOL)isFinished { - return _loaderCompleted; + return _loaderCompleted; } @end @@ -642,104 +646,114 @@ @implementation DOUAudioFileProvider + (instancetype)_fileProviderWithAudioFile:(id )audioFile { - if (audioFile == nil) { - return nil; - } - - NSURL *audioFileURL = [audioFile audioFileURL]; - if (audioFileURL == nil) { - return nil; - } - - if ([audioFileURL isFileURL]) { - return [[_DOUAudioLocalFileProvider alloc] _initWithAudioFile:audioFile]; - } + if (audioFile == nil) { + return nil; + } + + NSURL *audioFileURL = [audioFile audioFileURL]; + NSString *cacheFile = [[_DOUAudioRemoteFileProvider _cachedPathForAudioFileURL:audioFileURL] stringByDeletingPathExtension]; + + if ([[NSFileManager defaultManager] fileExistsAtPath:cacheFile isDirectory:NO]) { + + audioFileURL = [NSURL fileURLWithPath:cacheFile]; + [audioFile setAudioFileURL:audioFileURL]; + + } + + + if (audioFileURL == nil) { + return nil; + } + + if ([audioFileURL isFileURL]) { + return [[_DOUAudioLocalFileProvider alloc] _initWithAudioFile:audioFile]; + } #if TARGET_OS_IPHONE - else if ([[audioFileURL scheme] isEqualToString:@"ipod-library"]) { - return [[_DOUAudioMediaLibraryFileProvider alloc] _initWithAudioFile:audioFile]; - } + else if ([[audioFileURL scheme] isEqualToString:@"ipod-library"]) { + return [[_DOUAudioMediaLibraryFileProvider alloc] _initWithAudioFile:audioFile]; + } #endif /* TARGET_OS_IPHONE */ - else { - return [[_DOUAudioRemoteFileProvider alloc] _initWithAudioFile:audioFile]; - } + else { + return [[_DOUAudioRemoteFileProvider alloc] _initWithAudioFile:audioFile]; + } } + (instancetype)fileProviderWithAudioFile:(id )audioFile { - if ((audioFile == gHintFile || - [audioFile isEqual:gHintFile]) && - gHintProvider != nil) { - DOUAudioFileProvider *provider = gHintProvider; + if ((audioFile == gHintFile || + [audioFile isEqual:gHintFile]) && + gHintProvider != nil) { + DOUAudioFileProvider *provider = gHintProvider; + gHintFile = nil; + gHintProvider = nil; + gLastProviderIsFinished = [provider isFinished]; + + return provider; + } + gHintFile = nil; gHintProvider = nil; - gLastProviderIsFinished = [provider isFinished]; - - return provider; - } - - gHintFile = nil; - gHintProvider = nil; - gLastProviderIsFinished = NO; - - return [self _fileProviderWithAudioFile:audioFile]; + gLastProviderIsFinished = NO; + + return [self _fileProviderWithAudioFile:audioFile]; } + (void)setHintWithAudioFile:(id )audioFile { - if (audioFile == gHintFile || - [audioFile isEqual:gHintFile]) { - return; - } - - gHintFile = nil; - gHintProvider = nil; - - if (audioFile == nil) { - return; - } - - NSURL *audioFileURL = [audioFile audioFileURL]; - if (audioFileURL == nil || + if (audioFile == gHintFile || + [audioFile isEqual:gHintFile]) { + return; + } + + gHintFile = nil; + gHintProvider = nil; + + if (audioFile == nil) { + return; + } + + NSURL *audioFileURL = [audioFile audioFileURL]; + if (audioFileURL == nil || #if TARGET_OS_IPHONE - [[audioFileURL scheme] isEqualToString:@"ipod-library"] || + [[audioFileURL scheme] isEqualToString:@"ipod-library"] || #endif /* TARGET_OS_IPHONE */ - [audioFileURL isFileURL]) { - return; - } - - gHintFile = audioFile; - - if (gLastProviderIsFinished) { - gHintProvider = [self _fileProviderWithAudioFile:gHintFile]; - } + [audioFileURL isFileURL]) { + return; + } + + gHintFile = audioFile; + + if (gLastProviderIsFinished) { + gHintProvider = [self _fileProviderWithAudioFile:gHintFile]; + } } - (instancetype)_initWithAudioFile:(id )audioFile { - self = [super init]; - if (self) { - _audioFile = audioFile; - } - - return self; + self = [super init]; + if (self) { + _audioFile = audioFile; + } + + return self; } - (NSUInteger)downloadSpeed { - [self doesNotRecognizeSelector:_cmd]; - return 0; + [self doesNotRecognizeSelector:_cmd]; + return 0; } - (BOOL)isReady { - [self doesNotRecognizeSelector:_cmd]; - return NO; + [self doesNotRecognizeSelector:_cmd]; + return NO; } - (BOOL)isFinished { - [self doesNotRecognizeSelector:_cmd]; - return NO; + [self doesNotRecognizeSelector:_cmd]; + return NO; } @end