Renamed all Http classes to HTTP. Udpated STKHTTPDataSource to accept asynchronous URL providers. Chnaged STKAudioPlaye to always flush upcoming queue when currently playing track is seeked

This commit is contained in:
Thong Nguyen 2014-01-23 16:23:18 +00:00
parent 257532c6c9
commit 48ce1f9e67
10 changed files with 224 additions and 143 deletions

View File

@ -9,7 +9,7 @@
#import "AppDelegate.h"
#import "STKAudioPlayer.h"
#import "AudioPlayerView.h"
#import "STKAutoRecoveringHttpDataSource.h"
#import "STKAutoRecoveringHTTPDataSource.h"
#import "SampleQueueId.h"
#import <AVFoundation/AVFoundation.h>
@ -49,7 +49,7 @@
{
NSURL* url = [NSURL URLWithString:@"http://fs.bloom.fm/oss/audiosamples/sample.mp3"];
STKAutoRecoveringHttpDataSource* dataSource = [[STKAutoRecoveringHttpDataSource alloc] initWithHttpDataSource:(STKHttpDataSource*)[audioPlayer dataSourceFromURL:url]];
STKAutoRecoveringHTTPDataSource* dataSource = [[STKAutoRecoveringHTTPDataSource alloc] initWithHTTPDataSource:(STKHTTPDataSource*)[audioPlayer dataSourceFromURL:url]];
[audioPlayer setDataSource:dataSource withQueueItemId:[[SampleQueueId alloc] initWithUrl:url andCount:0]];
}

View File

@ -14,11 +14,11 @@
A1E7C4E6188D57F60010896F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1E7C4E4188D57F60010896F /* InfoPlist.strings */; };
A1E7C4E8188D57F60010896F /* StreamingKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4E7188D57F60010896F /* StreamingKitTests.m */; };
A1E7C4FF188D5E550010896F /* STKAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F2188D5E550010896F /* STKAudioPlayer.m */; };
A1E7C500188D5E550010896F /* STKAutoRecoveringHttpDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F4188D5E550010896F /* STKAutoRecoveringHttpDataSource.m */; };
A1E7C500188D5E550010896F /* STKAutoRecoveringHTTPDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F4188D5E550010896F /* STKAutoRecoveringHTTPDataSource.m */; };
A1E7C501188D5E550010896F /* STKCoreFoundationDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F6188D5E550010896F /* STKCoreFoundationDataSource.m */; };
A1E7C502188D5E550010896F /* STKDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F8188D5E550010896F /* STKDataSource.m */; };
A1E7C503188D5E550010896F /* STKDataSourceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FA188D5E550010896F /* STKDataSourceWrapper.m */; };
A1E7C504188D5E550010896F /* STKHttpDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FC188D5E550010896F /* STKHttpDataSource.m */; };
A1E7C504188D5E550010896F /* STKHTTPDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FC188D5E550010896F /* STKHTTPDataSource.m */; };
A1E7C505188D5E550010896F /* STKLocalFileDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FE188D5E550010896F /* STKLocalFileDataSource.m */; };
A1E7C508188D62D20010896F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E7C507188D62D20010896F /* UIKit.framework */; };
/* End PBXBuildFile section */
@ -56,16 +56,16 @@
A1E7C4E7188D57F60010896F /* StreamingKitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StreamingKitTests.m; sourceTree = "<group>"; };
A1E7C4F1188D5E550010896F /* STKAudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKAudioPlayer.h; sourceTree = "<group>"; };
A1E7C4F2188D5E550010896F /* STKAudioPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKAudioPlayer.m; sourceTree = "<group>"; };
A1E7C4F3188D5E550010896F /* STKAutoRecoveringHttpDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKAutoRecoveringHttpDataSource.h; sourceTree = "<group>"; };
A1E7C4F4188D5E550010896F /* STKAutoRecoveringHttpDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKAutoRecoveringHttpDataSource.m; sourceTree = "<group>"; };
A1E7C4F3188D5E550010896F /* STKAutoRecoveringHTTPDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKAutoRecoveringHTTPDataSource.h; sourceTree = "<group>"; };
A1E7C4F4188D5E550010896F /* STKAutoRecoveringHTTPDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKAutoRecoveringHTTPDataSource.m; sourceTree = "<group>"; };
A1E7C4F5188D5E550010896F /* STKCoreFoundationDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKCoreFoundationDataSource.h; sourceTree = "<group>"; };
A1E7C4F6188D5E550010896F /* STKCoreFoundationDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKCoreFoundationDataSource.m; sourceTree = "<group>"; };
A1E7C4F7188D5E550010896F /* STKDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKDataSource.h; sourceTree = "<group>"; };
A1E7C4F8188D5E550010896F /* STKDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKDataSource.m; sourceTree = "<group>"; };
A1E7C4F9188D5E550010896F /* STKDataSourceWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKDataSourceWrapper.h; sourceTree = "<group>"; };
A1E7C4FA188D5E550010896F /* STKDataSourceWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKDataSourceWrapper.m; sourceTree = "<group>"; };
A1E7C4FB188D5E550010896F /* STKHttpDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKHttpDataSource.h; sourceTree = "<group>"; };
A1E7C4FC188D5E550010896F /* STKHttpDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKHttpDataSource.m; sourceTree = "<group>"; };
A1E7C4FB188D5E550010896F /* STKHTTPDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKHTTPDataSource.h; sourceTree = "<group>"; };
A1E7C4FC188D5E550010896F /* STKHTTPDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKHTTPDataSource.m; sourceTree = "<group>"; };
A1E7C4FD188D5E550010896F /* STKLocalFileDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKLocalFileDataSource.h; sourceTree = "<group>"; };
A1E7C4FE188D5E550010896F /* STKLocalFileDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKLocalFileDataSource.m; sourceTree = "<group>"; };
A1E7C507188D62D20010896F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
@ -128,16 +128,16 @@
children = (
A1E7C4F1188D5E550010896F /* STKAudioPlayer.h */,
A1E7C4F2188D5E550010896F /* STKAudioPlayer.m */,
A1E7C4F3188D5E550010896F /* STKAutoRecoveringHttpDataSource.h */,
A1E7C4F4188D5E550010896F /* STKAutoRecoveringHttpDataSource.m */,
A1E7C4F3188D5E550010896F /* STKAutoRecoveringHTTPDataSource.h */,
A1E7C4F4188D5E550010896F /* STKAutoRecoveringHTTPDataSource.m */,
A1E7C4F5188D5E550010896F /* STKCoreFoundationDataSource.h */,
A1E7C4F6188D5E550010896F /* STKCoreFoundationDataSource.m */,
A1E7C4F7188D5E550010896F /* STKDataSource.h */,
A1E7C4F8188D5E550010896F /* STKDataSource.m */,
A1E7C4F9188D5E550010896F /* STKDataSourceWrapper.h */,
A1E7C4FA188D5E550010896F /* STKDataSourceWrapper.m */,
A1E7C4FB188D5E550010896F /* STKHttpDataSource.h */,
A1E7C4FC188D5E550010896F /* STKHttpDataSource.m */,
A1E7C4FB188D5E550010896F /* STKHTTPDataSource.h */,
A1E7C4FC188D5E550010896F /* STKHTTPDataSource.m */,
A1E7C4FD188D5E550010896F /* STKLocalFileDataSource.h */,
A1E7C4FE188D5E550010896F /* STKLocalFileDataSource.m */,
A1E7C4CE188D57F50010896F /* Supporting Files */,
@ -256,10 +256,10 @@
A1E7C501188D5E550010896F /* STKCoreFoundationDataSource.m in Sources */,
A1E7C4FF188D5E550010896F /* STKAudioPlayer.m in Sources */,
A1E7C505188D5E550010896F /* STKLocalFileDataSource.m in Sources */,
A1E7C504188D5E550010896F /* STKHttpDataSource.m in Sources */,
A1E7C504188D5E550010896F /* STKHTTPDataSource.m in Sources */,
A1E7C503188D5E550010896F /* STKDataSourceWrapper.m in Sources */,
A1E7C502188D5E550010896F /* STKDataSource.m in Sources */,
A1E7C500188D5E550010896F /* STKAutoRecoveringHttpDataSource.m in Sources */,
A1E7C500188D5E550010896F /* STKAutoRecoveringHTTPDataSource.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -132,6 +132,7 @@ AudioPlayerErrorCode;
-(void) queueDataSource:(STKDataSource*)dataSource withQueueItemId:(NSObject*)queueItemId;
-(void) setDataSource:(STKDataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId;
-(void) seekToTime:(double)value;
-(void) clearQueue;
-(void) pause;
-(void) resume;
-(void) stop;

View File

@ -37,7 +37,7 @@
#import "STKAudioPlayer.h"
#import "AudioToolbox/AudioToolbox.h"
#import "STKHttpDataSource.h"
#import "STKHTTPDataSource.h"
#import "STKLocalFileDataSource.h"
#import "libkern/OSAtomic.h"
@ -445,9 +445,9 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
self.state = newState;
dispatch_async(dispatch_get_main_queue(), ^
{
[self.delegate audioPlayer:self stateChanged:self.state];
});
{
[self.delegate audioPlayer:self stateChanged:self.state];
});
}
}
@ -599,7 +599,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
}
else
{
retval = [[STKHttpDataSource alloc] initWithURL:url];
retval = [[STKHTTPDataSource alloc] initWithURL:url];
}
return retval;
@ -635,13 +635,16 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
[upcomingQueue removeAllObjects];
dispatch_async(dispatch_get_main_queue(), ^
if (array.count > 0)
{
if ([self.delegate respondsToSelector:@selector(audioPlayer:didCancelQueuedItems:)])
dispatch_async(dispatch_get_main_queue(), ^
{
[self.delegate audioPlayer:self didCancelQueuedItems:array];
}
});
if ([self.delegate respondsToSelector:@selector(audioPlayer:didCancelQueuedItems:)])
{
[self.delegate audioPlayer:self didCancelQueuedItems:array];
}
});
}
}
pthread_mutex_unlock(&playerMutex);
}
@ -1209,24 +1212,24 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
if (runLoop)
{
CFRunLoopPerformBlock([runLoop getCFRunLoop], NSDefaultRunLoopMode, ^
{
pthread_mutex_lock(&playerMutex);
if (audioQueue)
{
[self stopAudioQueueWithReason:@"handlePropertyChangeForQueue`2"];
}
if (currentlyPlayingEntry)
{
self->stopReason = AudioPlayerStopReasonEof;
self.internalState = AudioPlayerInternalStateStopped;
[self processFinishedPlaying:currentlyPlayingEntry];
}
pthread_mutex_unlock(&playerMutex);
});
{
pthread_mutex_lock(&playerMutex);
if (audioQueue)
{
[self stopAudioQueueWithReason:@"handlePropertyChangeForQueue`2"];
}
if (currentlyPlayingEntry)
{
self->stopReason = AudioPlayerStopReasonEof;
self.internalState = AudioPlayerInternalStateStopped;
[self processFinishedPlaying:currentlyPlayingEntry];
}
pthread_mutex_unlock(&playerMutex);
});
CFRunLoopWakeUp([runLoop getCFRunLoop]);
}
@ -1371,6 +1374,13 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
audioQueue = nil;
}
if (currentlyPlayingEntry == nil)
{
pthread_mutex_unlock(&playerMutex);
return;
}
currentAudioStreamBasicDescription = currentlyPlayingEntry->audioStreamBasicDescription;
error = AudioQueueNewOutput(&currentAudioStreamBasicDescription, AudioQueueOutputCallbackProc, (__bridge void*)self, NULL, NULL, 0, &audioQueue);
@ -1381,9 +1391,9 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
{
[self.delegate audioPlayer:self didEncounterError:AudioPlayerErrorQueueCreationFailed];
});
pthread_mutex_unlock(&playerMutex);
pthread_mutex_unlock(&playerMutex);
return;
}
@ -1397,7 +1407,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
});
pthread_mutex_unlock(&playerMutex);
return;
}
@ -1497,7 +1507,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
{
[self.delegate audioPlayer:self didEncounterError:AudioPlayerErrorQueueCreationFailed];
});
pthread_mutex_unlock(&playerMutex);
return;
@ -1755,7 +1765,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
{
dispatch_async(dispatch_get_main_queue(), ^
{
[self.delegate audioPlayer:self didStartPlayingQueueItemId:playingQueueItemId];
[self.delegate audioPlayer:self didStartPlayingQueueItemId:playingQueueItemId];
});
}
}
@ -2082,6 +2092,8 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
currentEntry.bytesBuffered = 0;
currentEntry.firstFrameIndex = [self currentTimeInFrames];
[self clearQueue];
}
-(BOOL) startAudioQueue
@ -2337,15 +2349,37 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
[self logInfo:[NSString stringWithFormat:@"dataSourceEofLastByteIndex: %lld, %lld", audioPacketsReadCount, audioPacketsPlayedCount]];
if (audioPacketsReadCount == 0 && audioPacketsPlayedCount == audioPacketsReadCount)
if (audioPacketsReadCount == 0 && audioPacketsPlayedCount == audioPacketsReadCount && currentlyReadingEntry == currentlyPlayingEntry)
{
[self logInfo:@"dataSourceEof shutting down audio queue"];
[self logInfo:@"dataSourceEof seeked to end"];
if (audioQueue)
{
self.internalState = AudioPlayerInternalStateFlushingAndStoppingButStillPlaying;
AudioQueueStop(audioQueue, NO);
if ([self audioQueueIsRunning])
{
[self logInfo:@"dataSourceEof stopping audio queue asynchronously"];
AudioQueueStop(audioQueue, NO);
}
else
{
[self logInfo:@"dataSourceEof finished playing"];
if (audioQueue)
{
[self stopAudioQueueWithReason:@"dataSourceEof finished playing"];
}
if (currentlyPlayingEntry)
{
self->stopReason = AudioPlayerStopReasonEof;
self.internalState = AudioPlayerInternalStateStopped;
[self processFinishedPlaying:currentlyPlayingEntry];
}
}
}
}

View File

@ -33,13 +33,13 @@
**********************************************************************************/
#import "STKDataSource.h"
#import "STKHttpDataSource.h"
#import "STKHTTPDataSource.h"
#import "STKDataSourceWrapper.h"
@interface STKAutoRecoveringHttpDataSource : STKDataSourceWrapper
@interface STKAutoRecoveringHTTPDataSource : STKDataSourceWrapper
-(id) initWithHttpDataSource:(STKHttpDataSource*)innerDataSource;
-(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource;
@property (readonly) STKHttpDataSource* innerDataSource;
@property (readonly) STKHTTPDataSource* innerDataSource;
@end

View File

@ -40,12 +40,12 @@
#import <netdb.h>
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import "STKAutoRecoveringHttpDataSource.h"
#import "STKAutoRecoveringHTTPDataSource.h"
#define MAX_IMMEDIATE_RECONNECT_ATTEMPTS (8)
#define MAX_ATTEMPTS_WITH_SERVER_ERROR (MAX_IMMEDIATE_RECONNECT_ATTEMPTS + 2)
@interface STKAutoRecoveringHttpDataSource()
@interface STKAutoRecoveringHTTPDataSource()
{
int reconnectAttempts;
BOOL waitingForNetwork;
@ -60,25 +60,25 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
{
@autoreleasepool
{
STKAutoRecoveringHttpDataSource* dataSource = (__bridge STKAutoRecoveringHttpDataSource*)info;
STKAutoRecoveringHTTPDataSource* dataSource = (__bridge STKAutoRecoveringHTTPDataSource*)info;
[dataSource reachabilityChanged];
}
}
@implementation STKAutoRecoveringHttpDataSource
@implementation STKAutoRecoveringHTTPDataSource
-(STKHttpDataSource*) innerHttpDataSource
-(STKHTTPDataSource*) innerHTTPDataSource
{
return (STKHttpDataSource*)self.innerDataSource;
return (STKHTTPDataSource*)self.innerDataSource;
}
-(id) initWithDataSource:(STKDataSource *)innerDataSource
{
return [self initWithHttpDataSource:(STKHttpDataSource*)innerDataSource];
return [self initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource];
}
-(id) initWithHttpDataSource:(STKHttpDataSource*)innerDataSourceIn
-(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn
{
if (self = [super initWithDataSource:innerDataSourceIn])
{
@ -148,7 +148,7 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
-(void) dealloc
{
NSLog(@"STKAutoRecoveringHttpDataSource dealloc");
NSLog(@"STKAutoRecoveringHTTPDataSource dealloc");
self.innerDataSource.delegate = nil;

View File

@ -44,10 +44,13 @@
@interface STKCoreFoundationDataSource : STKDataSource
{
@protected
BOOL isInErrorState;
CFReadStreamRef stream;
NSRunLoop* eventsRunLoop;
}
@property (readonly) BOOL isInErrorState;
-(BOOL) reregisterForEvents;
-(void) dataAvailable;

View File

@ -60,6 +60,11 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
@implementation STKCoreFoundationDataSource
-(BOOL) isInErrorState
{
return self->isInErrorState;
}
-(void) dataAvailable
{
[self.delegate dataSourceDataAvailable:self];
@ -72,6 +77,8 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
-(void) errorOccured
{
self->isInErrorState = YES;
[self.delegate dataSourceErrorOccured:self];
}

View File

@ -34,15 +34,20 @@
#import "STKCoreFoundationDataSource.h"
typedef NSURL*(^URLProvider)();
@class STKHTTPDataSource;
@interface STKHttpDataSource : STKCoreFoundationDataSource
typedef void(^STKURLBlock)(NSURL* url);
typedef NSURL*(^STKURLProvider)();
typedef void(^STKAsyncURLProvider)(STKHTTPDataSource* dataSource, BOOL forSeek, STKURLBlock callback);
@interface STKHTTPDataSource : STKCoreFoundationDataSource
@property (readonly, retain) NSURL* url;
@property (readwrite) UInt32 httpStatusCode;
+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)fileExtension;
-(id) initWithURL:(NSURL*)url;
-(id) initWithURLProvider:(URLProvider)urlProvider;
-(id) initWithURLProvider:(STKURLProvider)urlProvider;
-(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProvider;
@end

View File

@ -32,10 +32,10 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "STKHttpDataSource.h"
#import "STKHTTPDataSource.h"
#import "STKLocalFileDataSource.h"
@interface STKHttpDataSource()
@interface STKHTTPDataSource()
{
@private
int seekStart;
@ -43,7 +43,7 @@
long long fileLength;
int discontinuous;
NSURL* currentUrl;
URLProvider urlProvider;
STKAsyncURLProvider asyncUrlProvider;
NSDictionary* httpHeaders;
AudioFileTypeID audioFileTypeHint;
}
@ -51,14 +51,24 @@
@end
@implementation STKHttpDataSource
@implementation STKHTTPDataSource
-(id) initWithURL:(NSURL*)urlIn
{
return [self initWithURLProvider:^NSURL* { return urlIn; }];
}
-(id) initWithURLProvider:(URLProvider)urlProviderIn
-(id) initWithURLProvider:(STKURLProvider)urlProviderIn
{
urlProviderIn = [urlProviderIn copy];
return [self initWithAsyncURLProvider:^(STKHTTPDataSource* dataSource, BOOL forSeek, STKURLBlock block)
{
block(urlProviderIn());
}];
}
-(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProviderIn
{
if (self = [super init])
{
@ -66,7 +76,7 @@
relativePosition = 0;
fileLength = -1;
self->urlProvider = [urlProviderIn copy];
self->asyncUrlProvider = [asyncUrlProviderIn copy];
[self open];
@ -78,7 +88,7 @@
-(void) dealloc
{
NSLog(@"STKHttpDataSource dealloc");
NSLog(@"STKHTTPDataSource dealloc");
}
-(NSURL*) url
@ -148,7 +158,7 @@
}
NSString* contentType = [httpHeaders objectForKey:@"Content-Type"];
AudioFileTypeID typeIdFromMimeType = [STKHttpDataSource audioFileTypeHintFromMimeType:contentType];
AudioFileTypeID typeIdFromMimeType = [STKHTTPDataSource audioFileTypeHintFromMimeType:contentType];
if (typeIdFromMimeType != 0)
{
@ -193,8 +203,9 @@
relativePosition = 0;
seekStart = (int)offset;
[self open];
[self reregisterForEvents];
self->isInErrorState = NO;
[self openForSeek:YES];
}
-(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size
@ -218,75 +229,95 @@
-(void) open
{
self->currentUrl = urlProvider();
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(NULL, (CFStringRef)@"GET", (__bridge CFURLRef)self->currentUrl, kCFHTTPVersion1_1);
if (seekStart > 0)
{
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Range"), (__bridge CFStringRef)[NSString stringWithFormat:@"bytes=%d-", seekStart]);
discontinuous = YES;
}
stream = CFReadStreamCreateForHTTPRequest(NULL, message);
if (stream == nil)
{
CFRelease(message);
[self errorOccured];
return;
}
if (!CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue))
{
CFRelease(message);
[self errorOccured];
return;
}
// Proxy support
CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPProxy, proxySettings);
CFRelease(proxySettings);
// SSL support
if ([self->currentUrl.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame)
{
NSDictionary* sslSettings = [NSDictionary dictionaryWithObjectsAndKeys:
(NSString*)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredRoots,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
[NSNull null], kCFStreamSSLPeerName,
nil];
CFReadStreamSetProperty(stream, kCFStreamPropertySSLSettings, (__bridge CFTypeRef)sslSettings);
}
// Open
if (!CFReadStreamOpen(stream))
{
CFRelease(stream);
CFRelease(message);
[self errorOccured];
return;
}
CFRelease(message);
return [self openForSeek:NO];
}
- (NSString *)description
-(void) openForSeek:(BOOL)forSeek
{
asyncUrlProvider(self, forSeek, ^(NSURL* url)
{
self->currentUrl = url;
if (url == nil)
{
return;
}
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(NULL, (CFStringRef)@"GET", (__bridge CFURLRef)self->currentUrl, kCFHTTPVersion1_1);
if (seekStart > 0)
{
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Range"), (__bridge CFStringRef)[NSString stringWithFormat:@"bytes=%d-", seekStart]);
discontinuous = YES;
}
stream = CFReadStreamCreateForHTTPRequest(NULL, message);
if (stream == nil)
{
CFRelease(message);
[self errorOccured];
return;
}
if (!CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue))
{
CFRelease(message);
[self errorOccured];
return;
}
// Proxy support
CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPProxy, proxySettings);
CFRelease(proxySettings);
// SSL support
if ([self->currentUrl.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame)
{
NSDictionary* sslSettings = [NSDictionary dictionaryWithObjectsAndKeys:
(NSString*)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredRoots,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
[NSNull null], kCFStreamSSLPeerName,
nil];
CFReadStreamSetProperty(stream, kCFStreamPropertySSLSettings, (__bridge CFTypeRef)sslSettings);
}
// Open
if (!CFReadStreamOpen(stream))
{
CFRelease(stream);
CFRelease(message);
[self errorOccured];
return;
}
self->isInErrorState = NO;
if (self->eventsRunLoop)
{
[self reregisterForEvents];
}
CFRelease(message);
});
}
-(NSString*) description
{
return [NSString stringWithFormat:@"HTTP data source with file length: %lld and position: %lld", self.length, self.position];
}