Compare commits

...

14 Commits

Author SHA1 Message Date
Thong Nguyen c9ba30b692 Removed iOS7 specific calls. Changed default target to iOS 4.3 2014-01-21 15:48:12 +00:00
Thong Nguyen c68384ec50 Added play:(NSString*) and playWithURL:(NSURL*) methods 2014-01-21 09:41:14 +00:00
Thong Nguyen 756504f33b Renamed QueueEntry to STKQueueEntry 2014-01-21 00:08:04 +00:00
Thong Nguyen 894dce8761 Updated README 2014-01-20 23:57:45 +00:00
Thong Nguyen c3a35fcdf3 Updated README 2014-01-20 23:57:18 +00:00
Thong Nguyen ce3f938309 Added playWithDataSource method. Updated README 2014-01-20 23:56:32 +00:00
Thong Nguyen 429c156d8b STKHttpDataSource now raises errors when failing to allocate resources for opening a stream 2014-01-20 23:47:55 +00:00
Thong Nguyen 0eb7687a63 Prevent crash when reading unsupported types and raise didEncounterError delegate callback 2014-01-20 23:22:41 +00:00
Thong Nguyen 9b952de734 Updated STKHttpDataSource to support dynamically generated URLs with each 'open' or 'seek') 2014-01-20 23:14:59 +00:00
Thong Nguyen 93e6f4b6d9 Fix namings of DataSources (added STK prefixes) 2014-01-20 22:30:35 +00:00
Thong Nguyen 9ed755cda4 Added kAudioFileAAC_ADTSType support 2014-01-20 21:11:00 +00:00
Thong Nguyen 7cc3f85a59 Fix README wiki link 2014-01-20 20:54:34 +00:00
Thong Nguyen a93d6867c5 Made the SampleApp support background playback. Updated README to point to wiki for background playbackr 2014-01-20 20:53:55 +00:00
Thong Nguyen 4660f0ce80 Fixed hard coded library search path in ExampleApp project 2014-01-20 19:22:48 +00:00
19 changed files with 330 additions and 234 deletions
@@ -23,6 +23,7 @@
A1115967188D6AEE00641365 /* AudioPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = A1115966188D6AEE00641365 /* AudioPlayerView.m */; };
A111596C188D6C8100641365 /* sample.m4a in Resources */ = {isa = PBXBuildFile; fileRef = A111596B188D6C8100641365 /* sample.m4a */; };
A111596F188D6DB100641365 /* SampleQueueId.m in Sources */ = {isa = PBXBuildFile; fileRef = A111596E188D6DB100641365 /* SampleQueueId.m */; };
A1EBEE64188DE34500681B04 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1EBEE63188DE34500681B04 /* SystemConfiguration.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -58,6 +59,7 @@
A111596B188D6C8100641365 /* sample.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; name = sample.m4a; path = Resources/sample.m4a; sourceTree = "<group>"; };
A111596D188D6DB100641365 /* SampleQueueId.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SampleQueueId.h; sourceTree = "<group>"; };
A111596E188D6DB100641365 /* SampleQueueId.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SampleQueueId.m; sourceTree = "<group>"; };
A1EBEE63188DE34500681B04 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -65,6 +67,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A1EBEE64188DE34500681B04 /* SystemConfiguration.framework in Frameworks */,
A1115964188D691500641365 /* libStreamingKit.a in Frameworks */,
A1115937188D686000641365 /* CoreGraphics.framework in Frameworks */,
A1115939188D686000641365 /* UIKit.framework in Frameworks */,
@@ -107,6 +110,7 @@
A1115933188D686000641365 /* Frameworks */ = {
isa = PBXGroup;
children = (
A1EBEE63188DE34500681B04 /* SystemConfiguration.framework */,
A1115963188D691500641365 /* libStreamingKit.a */,
A1115934188D686000641365 /* Foundation.framework */,
A1115936188D686000641365 /* CoreGraphics.framework */,
@@ -397,15 +401,13 @@
A111595E188D686000641365 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch";
INFOPLIST_FILE = "ExampleApp/ExampleApp-Info.plist";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/StreamingKit-dabtccqthoyywldsgcvllbcjcmma/Build/Products/Debug-iphoneos",
);
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -414,15 +416,13 @@
A111595F188D686000641365 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch";
INFOPLIST_FILE = "ExampleApp/ExampleApp-Info.plist";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/StreamingKit-dabtccqthoyywldsgcvllbcjcmma/Build/Products/Debug-iphoneos",
);
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
+9 -1
View File
@@ -9,7 +9,9 @@
#import "AppDelegate.h"
#import "STKAudioPlayer.h"
#import "AudioPlayerView.h"
#import "STKAutoRecoveringHttpDataSource.h"
#import "SampleQueueId.h"
#import <AVFoundation/AVFoundation.h>
@interface AppDelegate()
{
@@ -22,6 +24,10 @@
-(BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
NSError* error;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
@@ -43,7 +49,9 @@
{
NSURL* url = [NSURL URLWithString:@"http://fs.bloom.fm/oss/audiosamples/sample.mp3"];
[audioPlayer setDataSource:[audioPlayer dataSourceFromURL:url] withQueueItemId:[[SampleQueueId alloc] initWithUrl:url andCount:0]];
STKAutoRecoveringHttpDataSource* dataSource = [[STKAutoRecoveringHttpDataSource alloc] initWithHttpDataSource:(STKHttpDataSource*)[audioPlayer dataSourceFromURL:url]];
[audioPlayer setDataSource:dataSource withQueueItemId:[[SampleQueueId alloc] initWithUrl:url andCount:0]];
}
-(void) audioPlayerViewPlayFromLocalFileSelected:(AudioPlayerView*)audioPlayerView
@@ -24,6 +24,10 @@
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
+5 -8
View File
@@ -10,7 +10,7 @@ The primary motivation of this project was to decouple the input data sources fr
* Easy to read source
* Mostly asynchronous API
* Buffered and gapless playback
* Easy to implement audio data sources (HTTP and local file system DataSources provided)
* Easy to implement audio data sources (Local, HTTP, Auto Recovering HTTP DataSources are provided)
* Easy to extend DataSource to support adaptive buffering, encryption, etc.
* Optimised for low CPU/battery usage
@@ -20,25 +20,22 @@ StreamingKit is also available as a [Cocoapod](http://cocoapods.org/?q=Streaming
## Example
There are two main classes. The `STKDataSource` class which is the abstract base class for the various compressed audio data sources (HTTP, local file are provided). The `STKAudioPlayer` class manages and renders audio from a queue DataSources.
There are two main classes. The `STKDataSource` class which is the abstract base class for the various compressed audio data sources. The `STKAudioPlayer` class manages and renders audio from a queue DataSources. By default `STKAudioPlayer` will automatically parse URLs and create the appropriate data source internally.
```objective-c
// Create AudioPlayer
STKAudioPlayer* audioPlayer = [[STKAudioPlayer alloc] init];
audioPlayer.delegate = self;
// Queue on a URL to play. Each queue item has a unique ID (item1) that to identify the related file in delegate callbacks
[audioPlayer setDataSource:[audioPlayer dataSourceFromURL:@"http://fs.bloom.fm/oss/audiosamples/sample.mp3"] withQueueItemId:@"item1"];
[audioPlayer play:@"http://fs.bloom.fm/oss/audiosamples/sample.mp3"];
```
## Background Playback
## More
Background playback on iOS is easily added to your application by calling the `AudioSessionInitialize` in your AppDelegate and adding audio to the `UIBackgroundModes` key in your plist file.
More documentation is available on the project [wiki](https://github.com/tumtumtum/StreamingKit/wiki)
### Authors and Contributors
Copyright (c) 2012-2014, Thong Nguyen (@tumtumtum)
@@ -5,36 +5,36 @@
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
<false/>
<key>IDESourceControlProjectIdentifier</key>
<string>A5188B80-95E0-46CF-BEC9-273724D5616A</string>
<string>64C9BE2D-7DAD-476A-B9AC-1C4603CD4124</string>
<key>IDESourceControlProjectName</key>
<string>StreamingKit</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>821E27F3-2BD4-4B06-BB39-F4C3ECC1BBAD</key>
<string>https://github.com/tumtumtum/audjustable.git</string>
<key>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</key>
<string>https://github.com/tumtumtum/StreamingKit.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>StreamingKit.xcworkspace</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>821E27F3-2BD4-4B06-BB39-F4C3ECC1BBAD</key>
<key>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</key>
<string>..</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>https://github.com/tumtumtum/audjustable.git</string>
<string>https://github.com/tumtumtum/StreamingKit.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>110</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>821E27F3-2BD4-4B06-BB39-F4C3ECC1BBAD</string>
<string>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>821E27F3-2BD4-4B06-BB39-F4C3ECC1BBAD</string>
<string>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</string>
<key>IDESourceControlWCCName</key>
<string>audjustable</string>
<string>StreamingKit</string>
</dict>
</array>
</dict>
@@ -325,7 +325,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
@@ -357,7 +357,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
@@ -366,6 +366,7 @@
A1E7C4EC188D57F60010896F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD)";
DSTROOT = /tmp/StreamingKit.dst;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -382,6 +383,7 @@
A1E7C4ED188D57F60010896F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD)";
DSTROOT = /tmp/StreamingKit.dst;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -452,6 +454,7 @@
A1E7C4ED188D57F60010896F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A1E7C4EE188D57F60010896F /* Build configuration list for PBXNativeTarget "StreamingKitTests" */ = {
isa = XCConfigurationList;
@@ -460,6 +463,7 @@
A1E7C4F0188D57F60010896F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
+11 -69
View File
@@ -44,7 +44,7 @@
#include "UIKit/UIApplication.h"
#endif
#define AudioPlayerDefaultNumberOfAudioQueueBuffers (2 * 1024)
#define AudioPlayerDefaultNumberOfAudioQueueBuffers (10 * 1024)
typedef enum
{
@@ -94,10 +94,12 @@ typedef enum
AudioPlayerErrorQueuePauseFailed,
AudioPlayerErrorUnknownBuffer,
AudioPlayerErrorQueueStopFailed,
AudioPlayerErrorOther
AudioPlayerErrorQueueCreationFailed,
AudioPlayerErrorOther = -1
}
AudioPlayerErrorCode;
@class STKDataSource;
@class STKAudioPlayer;
@protocol STKAudioPlayerDelegate <NSObject>
@@ -112,7 +114,7 @@ AudioPlayerErrorCode;
-(void) audioPlayer: (STKAudioPlayer*)audioPlayer didCancelQueuedItems:(NSArray*)queuedItems;
@end
@class QueueEntry;
@class STKQueueEntry;
typedef struct
{
@@ -122,68 +124,6 @@ typedef struct
AudioQueueBufferRefLookupEntry;
@interface STKAudioPlayer : NSObject<STKDataSourceDelegate>
{
@private
UInt8* readBuffer;
int readBufferSize;
NSOperationQueue* fastApiQueue;
QueueEntry* currentlyPlayingEntry;
QueueEntry* currentlyReadingEntry;
NSMutableArray* upcomingQueue;
NSMutableArray* bufferingQueue;
AudioQueueBufferRef* audioQueueBuffer;
AudioQueueBufferRefLookupEntry* audioQueueBufferLookup;
unsigned int audioQueueBufferRefLookupCount;
unsigned int audioQueueBufferCount;
AudioStreamPacketDescription* packetDescs;
bool* bufferUsed;
int numberOfBuffersUsed;
AudioQueueRef audioQueue;
AudioStreamBasicDescription currentAudioStreamBasicDescription;
NSThread* playbackThread;
NSRunLoop* playbackThreadRunLoop;
NSConditionLock* threadFinishedCondLock;
AudioFileStreamID audioFileStream;
BOOL discontinuous;
int bytesFilled;
int packetsFilled;
int fillBufferIndex;
#if TARGET_OS_IPHONE
UIBackgroundTaskIdentifier backgroundTaskId;
#endif
AudioPlayerErrorCode errorCode;
AudioPlayerStopReason stopReason;
int currentlyPlayingLock;
pthread_mutex_t playerMutex;
pthread_mutex_t queueBuffersMutex;
pthread_cond_t queueBufferReadyCondition;
volatile BOOL waiting;
volatile BOOL disposeWasRequested;
volatile BOOL seekToTimeWasRequested;
volatile BOOL newFileToPlay;
volatile double requestedSeekTime;
volatile BOOL audioQueueFlushing;
volatile SInt64 audioPacketsReadCount;
volatile SInt64 audioPacketsPlayedCount;
BOOL meteringEnabled;
AudioQueueLevelMeterState* levelMeterState;
NSInteger numberOfChannels;
}
@property (readonly) double duration;
@property (readonly) double progress;
@@ -194,10 +134,12 @@ AudioQueueBufferRefLookupEntry;
-(id) init;
-(id) initWithNumberOfAudioQueueBuffers:(int)numberOfAudioQueueBuffers andReadBufferSize:(int)readBufferSizeIn;
-(DataSource*) dataSourceFromURL:(NSURL*)url;
-(void) play:(NSURL*)url;
-(void) queueDataSource:(DataSource*)dataSource withQueueItemId:(NSObject*)queueItemId;
-(void) setDataSource:(DataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId;
-(STKDataSource*) dataSourceFromURL:(NSURL*)url;
-(void) play:(NSString*)urlString;
-(void) playWithURL:(NSURL*)url;
-(void) playWithDataSource:(STKDataSource*)dataSource;
-(void) queueDataSource:(STKDataSource*)dataSource withQueueItemId:(NSObject*)queueItemId;
-(void) setDataSource:(STKDataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId;
-(void) seekToTime:(double)value;
-(void) pause;
-(void) resume;
+165 -50
View File
@@ -97,7 +97,7 @@
@end
@interface QueueEntry : NSObject
@interface STKQueueEntry : NSObject
{
@public
BOOL parsedHeader;
@@ -114,7 +114,7 @@
AudioStreamBasicDescription audioStreamBasicDescription;
}
@property (readwrite, retain) NSObject* queueItemId;
@property (readwrite, retain) DataSource* dataSource;
@property (readwrite, retain) STKDataSource* dataSource;
@property (readwrite) int bufferIndex;
@property (readonly) UInt64 audioDataLengthInBytes;
@@ -122,20 +122,20 @@
-(double) calculatedBitRate;
-(double) progress;
-(id) initWithDataSource:(DataSource*)dataSource andQueueItemId:(NSObject*)queueItemId;
-(id) initWithDataSource:(DataSource*)dataSource andQueueItemId:(NSObject*)queueItemId andBufferIndex:(int)bufferIndex;
-(id) initWithDataSource:(STKDataSource*)dataSource andQueueItemId:(NSObject*)queueItemId;
-(id) initWithDataSource:(STKDataSource*)dataSource andQueueItemId:(NSObject*)queueItemId andBufferIndex:(int)bufferIndex;
@end
@implementation QueueEntry
@implementation STKQueueEntry
@synthesize dataSource, queueItemId, bufferIndex;
-(id) initWithDataSource:(DataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn
-(id) initWithDataSource:(STKDataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn
{
return [self initWithDataSource:dataSourceIn andQueueItemId:queueItemIdIn andBufferIndex:-1];
}
-(id) initWithDataSource:(DataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn andBufferIndex:(int)bufferIndexIn
-(id) initWithDataSource:(STKDataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn andBufferIndex:(int)bufferIndexIn
{
if (self = [super init])
{
@@ -246,6 +246,68 @@
@end
@interface STKAudioPlayer()
{
UInt8* readBuffer;
int readBufferSize;
NSOperationQueue* fastApiQueue;
STKQueueEntry* currentlyPlayingEntry;
STKQueueEntry* currentlyReadingEntry;
NSMutableArray* upcomingQueue;
NSMutableArray* bufferingQueue;
AudioQueueBufferRef* audioQueueBuffer;
AudioQueueBufferRefLookupEntry* audioQueueBufferLookup;
unsigned int audioQueueBufferRefLookupCount;
unsigned int audioQueueBufferCount;
AudioStreamPacketDescription* packetDescs;
bool* bufferUsed;
int numberOfBuffersUsed;
AudioQueueRef audioQueue;
AudioStreamBasicDescription currentAudioStreamBasicDescription;
NSThread* playbackThread;
NSRunLoop* playbackThreadRunLoop;
NSConditionLock* threadFinishedCondLock;
AudioFileStreamID audioFileStream;
BOOL discontinuous;
int bytesFilled;
int packetsFilled;
int fillBufferIndex;
#if TARGET_OS_IPHONE
UIBackgroundTaskIdentifier backgroundTaskId;
#endif
AudioPlayerErrorCode errorCode;
AudioPlayerStopReason stopReason;
int currentlyPlayingLock;
pthread_mutex_t playerMutex;
pthread_mutex_t queueBuffersMutex;
pthread_cond_t queueBufferReadyCondition;
volatile BOOL waiting;
volatile BOOL disposeWasRequested;
volatile BOOL seekToTimeWasRequested;
volatile BOOL newFileToPlay;
volatile double requestedSeekTime;
volatile BOOL audioQueueFlushing;
volatile SInt64 audioPacketsReadCount;
volatile SInt64 audioPacketsPlayedCount;
BOOL meteringEnabled;
AudioQueueLevelMeterState* levelMeterState;
NSInteger numberOfChannels;
}
@property (readwrite) AudioPlayerInternalState internalState;
-(void) logInfo:(NSString*)line;
@@ -257,11 +319,11 @@
-(void) stopAudioQueueWithReason:(NSString*)reason;
-(BOOL) processRunloop;
-(void) wakeupPlaybackThread;
-(void) audioQueueFinishedPlaying:(QueueEntry*)entry;
-(void) audioQueueFinishedPlaying:(STKQueueEntry*)entry;
-(void) processSeekToTime;
-(void) didEncounterError:(AudioPlayerErrorCode)errorCode;
-(void) setInternalState:(AudioPlayerInternalState)value;
-(void) processDidFinishPlaying:(QueueEntry*)entry withNext:(QueueEntry*)next;
-(void) processDidFinishPlaying:(STKQueueEntry*)entry withNext:(STKQueueEntry*)next;
-(void) handlePropertyChangeForFileStream:(AudioFileStreamID)audioFileStreamIn fileStreamPropertyID:(AudioFileStreamPropertyID)propertyID ioFlags:(UInt32*)ioFlags;
-(void) handleAudioPackets:(const void*)inputData numberBytes:(UInt32)numberBytes numberPackets:(UInt32)numberPackets packetDescriptions:(AudioStreamPacketDescription*)packetDescriptions;
-(void) handleAudioQueueOutput:(AudioQueueRef)audioQueue buffer:(AudioQueueBufferRef)buffer;
@@ -316,9 +378,9 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
if ([self.delegate respondsToSelector:@selector(audioPlayer:internalStateChanged:)])
{
dispatch_async(dispatch_get_main_queue(), ^
{
[self.delegate audioPlayer:self internalStateChanged:internalState];
});
{
[self.delegate audioPlayer:self internalStateChanged:internalState];
});
}
AudioPlayerState newState;
@@ -500,17 +562,17 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
#endif
}
-(DataSource*) dataSourceFromURL:(NSURL*)url
-(STKDataSource*) dataSourceFromURL:(NSURL*)url
{
DataSource* retval;
STKDataSource* retval;
if ([url.scheme isEqualToString:@"file"])
{
retval = [[LocalFileDataSource alloc] initWithFilePath:url.path];
retval = [[STKLocalFileDataSource alloc] initWithFilePath:url.path];
}
else
{
retval = [[HttpDataSource alloc] initWithURL:url];
retval = [[STKHttpDataSource alloc] initWithURL:url];
}
return retval;
@@ -522,7 +584,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
{
NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity:bufferingQueue.count + upcomingQueue.count];
QueueEntry* entry = [bufferingQueue dequeue];
STKQueueEntry* entry = [bufferingQueue dequeue];
if (entry && entry != currentlyPlayingEntry)
{
@@ -531,10 +593,15 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
while (bufferingQueue.count > 0)
{
[array addObject:[[bufferingQueue dequeue] queueItemId]];
id queueItemId = [[bufferingQueue dequeue] queueItemId];
if (queueItemId != nil)
{
[array addObject:queueItemId];
}
}
for (QueueEntry* entry in upcomingQueue)
for (STKQueueEntry* entry in upcomingQueue)
{
[array addObject:entry.queueItemId];
}
@@ -542,22 +609,35 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
[upcomingQueue removeAllObjects];
dispatch_async(dispatch_get_main_queue(), ^
{
if ([self.delegate respondsToSelector:@selector(audioPlayer:didCancelQueuedItems:)])
{
[self.delegate audioPlayer:self didCancelQueuedItems:array];
}
});
{
if ([self.delegate respondsToSelector:@selector(audioPlayer:didCancelQueuedItems:)])
{
[self.delegate audioPlayer:self didCancelQueuedItems:array];
}
});
}
pthread_mutex_unlock(&playerMutex);
}
-(void) play:(NSURL*)url
-(void) play:(NSString*)urlString
{
NSURL* url = [NSURL URLWithString:urlString];
[self setDataSource:[self dataSourceFromURL:url] withQueueItemId:urlString];
}
-(void) playWithURL:(NSURL*)url
{
[self setDataSource:[self dataSourceFromURL:url] withQueueItemId:url];
}
-(void) setDataSource:(DataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId
-(void) playWithDataSource:(STKDataSource*)dataSource
{
[self setDataSource:dataSource withQueueItemId:dataSource];
}
-(void) setDataSource:(STKDataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId
{
[fastApiQueue cancelAllOperations];
@@ -569,7 +649,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
[self clearQueue];
[upcomingQueue enqueue:[[QueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]];
[upcomingQueue enqueue:[[STKQueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]];
self.internalState = AudioPlayerInternalStateRunning;
[self processQueue:YES];
@@ -578,13 +658,13 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
}];
}
-(void) queueDataSource:(DataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId
-(void) queueDataSource:(STKDataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId
{
[fastApiQueue addOperationWithBlock:^
{
pthread_mutex_lock(&playerMutex);
{
[upcomingQueue enqueue:[[QueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]];
[upcomingQueue enqueue:[[STKQueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]];
[self processQueue:NO];
}
@@ -717,12 +797,22 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
if (audioQueue == nil)
{
[self createAudioQueue];
if (audioQueue == nil)
{
return;
}
}
else if (memcmp(&currentAudioStreamBasicDescription, &currentlyReadingEntry->audioStreamBasicDescription, sizeof(currentAudioStreamBasicDescription)) != 0)
{
if (currentlyReadingEntry == currentlyPlayingEntry)
{
[self createAudioQueue];
if (audioQueue == nil)
{
return;
}
}
else
{
@@ -774,7 +864,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
}
AudioQueueBufferRef bufferToFill = audioQueueBuffer[fillBufferIndex];
memcpy((char*)bufferToFill->mAudioData + bytesFilled, (const char*)inputData + packetOffset, packetSize);
memcpy((char*)bufferToFill->mAudioData + bytesFilled, (const char*)inputData + packetOffset, (unsigned long)packetSize);
packetDescs[packetsFilled] = packetDescriptionsIn[i];
packetDescs[packetsFilled].mStartOffset = bytesFilled;
@@ -858,7 +948,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
return;
}
QueueEntry* entry = nil;
STKQueueEntry* entry = nil;
if (currentlyPlayingEntry)
{
@@ -1140,6 +1230,11 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
if (error)
{
dispatch_async(dispatch_get_main_queue(), ^
{
[self.delegate audioPlayer:self didEncounterError:AudioPlayerErrorQueueCreationFailed];
});
return;
}
@@ -1147,6 +1242,8 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
if (error)
{
[self.delegate audioPlayer:self didEncounterError:AudioPlayerErrorQueueCreationFailed];
return;
}
@@ -1188,6 +1285,11 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
if (error)
{
dispatch_async(dispatch_get_main_queue(), ^
{
[self.delegate audioPlayer:self didEncounterError:AudioPlayerErrorQueueCreationFailed];
});
return;
}
}
@@ -1204,6 +1306,11 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
if (error)
{
dispatch_async(dispatch_get_main_queue(), ^
{
[self.delegate audioPlayer:self didEncounterError:AudioPlayerErrorQueueCreationFailed];
});
return;
}
@@ -1224,6 +1331,11 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
{
free(cookieData);
dispatch_async(dispatch_get_main_queue(), ^
{
[self.delegate audioPlayer:self didEncounterError:AudioPlayerErrorQueueCreationFailed];
});
return;
}
@@ -1245,7 +1357,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
OSSpinLockLock(&currentlyPlayingLock);
QueueEntry* entry = currentlyPlayingEntry;
STKQueueEntry* entry = currentlyPlayingEntry;
if (entry == nil)
{
@@ -1275,7 +1387,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
OSSpinLockLock(&currentlyPlayingLock);
QueueEntry* entry = currentlyPlayingEntry;
STKQueueEntry* entry = currentlyPlayingEntry;
if (entry == nil)
{
@@ -1358,7 +1470,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
}
}
-(void) setCurrentlyReadingEntry:(QueueEntry*)entry andStartPlaying:(BOOL)startPlaying
-(void) setCurrentlyReadingEntry:(STKQueueEntry*)entry andStartPlaying:(BOOL)startPlaying
{
pthread_mutex_lock(&queueBuffersMutex);
@@ -1412,13 +1524,13 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
pthread_mutex_unlock(&queueBuffersMutex);
}
-(void) audioQueueFinishedPlaying:(QueueEntry*)entry
-(void) audioQueueFinishedPlaying:(STKQueueEntry*)entry
{
pthread_mutex_lock(&playerMutex);
{
pthread_mutex_lock(&queueBuffersMutex);
{
QueueEntry* next = [bufferingQueue dequeue];
STKQueueEntry* next = [bufferingQueue dequeue];
[self processDidFinishPlaying:entry withNext:next];
}
@@ -1427,7 +1539,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
pthread_mutex_unlock(&playerMutex);
}
-(void) processDidFinishPlaying:(QueueEntry*)entry withNext:(QueueEntry*)next
-(void) processDidFinishPlaying:(STKQueueEntry*)entry withNext:(STKQueueEntry*)next
{
if (entry != currentlyPlayingEntry)
{
@@ -1508,7 +1620,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
}
else if (newFileToPlay)
{
QueueEntry* entry = [upcomingQueue dequeue];
STKQueueEntry* entry = [upcomingQueue dequeue];
self.internalState = AudioPlayerInternalStateWaitingForData;
@@ -1584,7 +1696,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
{
BOOL nextIsIncompatible = NO;
QueueEntry* next = [bufferingQueue peek];
STKQueueEntry* next = [bufferingQueue peek];
if (next == nil)
{
@@ -1610,7 +1722,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
{
if (upcomingQueue.count > 0)
{
QueueEntry* entry = [upcomingQueue dequeue];
STKQueueEntry* entry = [upcomingQueue dequeue];
BOOL startPlaying = currentlyPlayingEntry == nil;
BOOL wasCurrentlyPlayingNothing = currentlyPlayingEntry == nil;
@@ -1655,7 +1767,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
[bufferingQueue dequeue];
}
QueueEntry* newEntry = [[QueueEntry alloc] initWithDataSource:currentlyReadingEntry.dataSource andQueueItemId:currentlyReadingEntry.queueItemId];
STKQueueEntry* newEntry = [[STKQueueEntry alloc] initWithDataSource:currentlyReadingEntry.dataSource andQueueItemId:currentlyReadingEntry.queueItemId];
newEntry->audioStreamBasicDescription = currentlyReadingEntry->audioStreamBasicDescription;
@@ -1730,7 +1842,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
{
OSStatus error;
OSSpinLockLock(&currentlyPlayingLock);
QueueEntry* currentEntry = currentlyReadingEntry;
STKQueueEntry* currentEntry = currentlyReadingEntry;
OSSpinLockUnlock(&currentlyPlayingLock);
NSAssert(currentEntry == currentlyPlayingEntry, @"playing and reading must be the same");
@@ -1811,9 +1923,12 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
[self stopAudioQueueWithReason:@"from startAudioQueue"];
[self createAudioQueue];
self.internalState = AudioPlayerInternalStateWaitingForQueueToStart;
AudioQueueStart(audioQueue, NULL);
if (audioQueue != nil)
{
self.internalState = AudioPlayerInternalStateWaitingForQueueToStart;
AudioQueueStart(audioQueue, NULL);
}
}
[self stopSystemBackgroundTask];
@@ -1926,7 +2041,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
pthread_mutex_unlock(&queueBuffersMutex);
}
-(void) dataSourceDataAvailable:(DataSource*)dataSourceIn
-(void) dataSourceDataAvailable:(STKDataSource*)dataSourceIn
{
OSStatus error;
@@ -1989,7 +2104,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
}
}
-(void) dataSourceErrorOccured:(DataSource*)dataSourceIn
-(void) dataSourceErrorOccured:(STKDataSource*)dataSourceIn
{
if (currentlyReadingEntry.dataSource != dataSourceIn)
{
@@ -1999,7 +2114,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
[self didEncounterError:AudioPlayerErrorDataNotFound];
}
-(void) dataSourceEof:(DataSource*)dataSourceIn
-(void) dataSourceEof:(STKDataSource*)dataSourceIn
{
if (currentlyReadingEntry.dataSource != dataSourceIn)
{
@@ -2193,7 +2308,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
{
OSSpinLockLock(&currentlyPlayingLock);
QueueEntry* entry = currentlyPlayingEntry;
STKQueueEntry* entry = currentlyPlayingEntry;
if (entry == nil)
{
@@ -36,10 +36,10 @@
#import "STKHttpDataSource.h"
#import "STKDataSourceWrapper.h"
@interface STKAutoRecoveringHttpDataSource : DataSourceWrapper
@interface STKAutoRecoveringHttpDataSource : STKDataSourceWrapper
-(id) initWithHttpDataSource:(HttpDataSource*)innerDataSource;
-(id) initWithHttpDataSource:(STKHttpDataSource*)innerDataSource;
@property (readonly) HttpDataSource* innerDataSource;
@property (readonly) STKHttpDataSource* innerDataSource;
@end
@@ -68,12 +68,17 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
@implementation STKAutoRecoveringHttpDataSource
-(HttpDataSource*) innerHttpDataSource
-(STKHttpDataSource*) innerHttpDataSource
{
return (HttpDataSource*)self.innerDataSource;
return (STKHttpDataSource*)self.innerDataSource;
}
-(id) initWithHttpDataSource:(HttpDataSource*)innerDataSourceIn
-(id) initWithDataSource:(STKDataSource *)innerDataSource
{
return [self initWithHttpDataSource:(STKHttpDataSource*)innerDataSource];
}
-(id) initWithHttpDataSource:(STKHttpDataSource*)innerDataSourceIn
{
if (self = [super initWithDataSource:innerDataSourceIn])
{
@@ -143,6 +148,8 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
-(void) dealloc
{
NSLog(@"STKAutoRecoveringHttpDataSource dealloc");
self.innerDataSource.delegate = nil;
[self stopNotifier];
@@ -165,7 +172,7 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
}
}
-(void) dataSourceDataAvailable:(DataSource*)dataSource
-(void) dataSourceDataAvailable:(STKDataSource*)dataSource
{
reconnectAttempts = 0;
@@ -202,7 +209,7 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
}
}
-(void) dataSourceEof:(DataSource*)dataSource
-(void) dataSourceEof:(STKDataSource*)dataSource
{
if ([self position] != [self length])
{
@@ -214,7 +221,7 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
[self.delegate dataSourceEof:self];
}
-(void) dataSourceErrorOccured:(DataSource*)dataSource
-(void) dataSourceErrorOccured:(STKDataSource*)dataSource
{
if (self.innerDataSource.httpStatusCode == 416 /* Range out of bounds */)
{
@@ -41,7 +41,7 @@
@property (readwrite, retain) STKCoreFoundationDataSource* datasource;
@end
@interface STKCoreFoundationDataSource : DataSource
@interface STKCoreFoundationDataSource : STKDataSource
{
@protected
CFReadStreamRef stream;
+5 -5
View File
@@ -35,12 +35,12 @@
#import <Foundation/Foundation.h>
#include <AudioToolbox/AudioToolbox.h>
@class DataSource;
@class STKDataSource;
@protocol STKDataSourceDelegate<NSObject>
-(void) dataSourceDataAvailable:(DataSource*)dataSource;
-(void) dataSourceErrorOccured:(DataSource*)dataSource;
-(void) dataSourceEof:(DataSource*)dataSource;
-(void) dataSourceDataAvailable:(STKDataSource*)dataSource;
-(void) dataSourceErrorOccured:(STKDataSource*)dataSource;
-(void) dataSourceEof:(STKDataSource*)dataSource;
@end
@protocol AudioDataSource<NSObject>
@@ -48,7 +48,7 @@
@property (readwrite) long long audioDataOffset;
@end
@interface DataSource : NSObject
@interface STKDataSource : NSObject
@property (readonly) long long position;
@property (readonly) long long length;
+1 -1
View File
@@ -34,7 +34,7 @@
#import "STKDataSource.h"
@implementation DataSource
@implementation STKDataSource
@synthesize delegate;
-(long long) length
@@ -34,10 +34,10 @@
#import "STKDataSource.h"
@interface DataSourceWrapper : DataSource<STKDataSourceDelegate>
@interface STKDataSourceWrapper : STKDataSource<STKDataSourceDelegate>
-(id) initWithDataSource:(DataSource*)innerDataSource;
-(id) initWithDataSource:(STKDataSource*)innerDataSource;
@property (readonly) DataSource* innerDataSource;
@property (readonly) STKDataSource* innerDataSource;
@end
@@ -34,13 +34,13 @@
#import "STKDataSourceWrapper.h"
@interface DataSourceWrapper()
@property (readwrite) DataSource* innerDataSource;
@interface STKDataSourceWrapper()
@property (readwrite) STKDataSource* innerDataSource;
@end
@implementation DataSourceWrapper
@implementation STKDataSourceWrapper
-(id) initWithDataSource:(DataSource*)innerDataSourceIn
-(id) initWithDataSource:(STKDataSource*)innerDataSourceIn
{
if (self = [super init])
{
@@ -102,17 +102,17 @@
return self.innerDataSource.hasBytesAvailable;
}
-(void) dataSourceDataAvailable:(DataSource*)dataSource
-(void) dataSourceDataAvailable:(STKDataSource*)dataSource
{
[self.delegate dataSourceDataAvailable:self];
}
-(void) dataSourceErrorOccured:(DataSource*)dataSource
-(void) dataSourceErrorOccured:(STKDataSource*)dataSource
{
[self.delegate dataSourceErrorOccured:self];
}
-(void) dataSourceEof:(DataSource*)dataSource
-(void) dataSourceEof:(STKDataSource*)dataSource
{
[self.delegate dataSourceEof:self];
}
+5 -11
View File
@@ -34,21 +34,15 @@
#import "STKCoreFoundationDataSource.h"
@interface HttpDataSource : STKCoreFoundationDataSource
{
@private
int seekStart;
int relativePosition;
long long fileLength;
int discontinuous;
NSDictionary* httpHeaders;
AudioFileTypeID audioFileTypeHint;
}
typedef NSURL*(^URLProvider)();
@property (readwrite, retain) NSURL* url;
@interface STKHttpDataSource : STKCoreFoundationDataSource
@property (readonly, retain) NSURL* url;
@property (readwrite) UInt32 httpStatusCode;
+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)fileExtension;
-(id) initWithURL:(NSURL*)url;
-(id) initWithURLProvider:(URLProvider)urlProvider;
@end
+62 -27
View File
@@ -35,14 +35,30 @@
#import "STKHttpDataSource.h"
#import "STKLocalFileDataSource.h"
@interface HttpDataSource()
@interface STKHttpDataSource()
{
@private
int seekStart;
int relativePosition;
long long fileLength;
int discontinuous;
NSURL* currentUrl;
URLProvider urlProvider;
NSDictionary* httpHeaders;
AudioFileTypeID audioFileTypeHint;
}
-(void) open;
@end
@implementation HttpDataSource
@synthesize url;
@implementation STKHttpDataSource
-(id) initWithURL:(NSURL*)urlIn
{
return [self initWithURLProvider:^NSURL* { return urlIn; }];
}
-(id) initWithURLProvider:(URLProvider)urlProviderIn
{
if (self = [super init])
{
@@ -50,41 +66,52 @@
relativePosition = 0;
fileLength = -1;
self.url = urlIn;
self->urlProvider = urlProviderIn;
[self open];
audioFileTypeHint = [LocalFileDataSource audioFileTypeHintFromFileExtension:urlIn.pathExtension];
audioFileTypeHint = [STKLocalFileDataSource audioFileTypeHintFromFileExtension:self->currentUrl.pathExtension];
}
return self;
}
-(void) dealloc
{
NSLog(@"STKHttpDataSource dealloc");
}
-(NSURL*) url
{
return self->currentUrl;
}
+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)mimeType
{
static dispatch_once_t onceToken;
static NSDictionary* fileTypesByMimeType;
dispatch_once(&onceToken, ^
{
fileTypesByMimeType =
@{
@"audio/mp3": @(kAudioFileMP3Type),
@"audio/mpg": @(kAudioFileMP3Type),
@"audio/mpeg": @(kAudioFileMP3Type),
@"audio/wav": @(kAudioFileWAVEType),
@"audio/aifc": @(kAudioFileAIFCType),
@"audio/aiff": @(kAudioFileAIFFType),
@"audio/x-m4a": @(kAudioFileM4AType),
@"audio/x-mp4": @(kAudioFileMPEG4Type),
@"audio/m4a": @(kAudioFileM4AType),
@"audio/mp4": @(kAudioFileMPEG4Type),
@"audio/caf": @(kAudioFileCAFType),
@"audio/aac": @(kAudioFileAAC_ADTSType),
@"audio/ac3": @(kAudioFileAC3Type),
@"audio/3gp": @(kAudioFile3GPType)
};
});
{
fileTypesByMimeType =
@{
@"audio/mp3": @(kAudioFileMP3Type),
@"audio/mpg": @(kAudioFileMP3Type),
@"audio/mpeg": @(kAudioFileMP3Type),
@"audio/wav": @(kAudioFileWAVEType),
@"audio/aifc": @(kAudioFileAIFCType),
@"audio/aiff": @(kAudioFileAIFFType),
@"audio/x-m4a": @(kAudioFileM4AType),
@"audio/x-mp4": @(kAudioFileMPEG4Type),
@"audio/aacp": @(kAudioFileAAC_ADTSType),
@"audio/m4a": @(kAudioFileM4AType),
@"audio/mp4": @(kAudioFileMPEG4Type),
@"audio/caf": @(kAudioFileCAFType),
@"audio/aac": @(kAudioFileAAC_ADTSType),
@"audio/ac3": @(kAudioFileAC3Type),
@"audio/3gp": @(kAudioFile3GPType)
};
});
NSNumber* number = [fileTypesByMimeType objectForKey:mimeType];
@@ -121,7 +148,7 @@
}
NSString* contentType = [httpHeaders objectForKey:@"Content-Type"];
AudioFileTypeID typeIdFromMimeType = [HttpDataSource audioFileTypeHintFromMimeType:contentType];
AudioFileTypeID typeIdFromMimeType = [STKHttpDataSource audioFileTypeHintFromMimeType:contentType];
if (typeIdFromMimeType != 0)
{
@@ -191,7 +218,9 @@
-(void) open
{
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(NULL, (CFStringRef)@"GET", (__bridge CFURLRef)self.url, kCFHTTPVersion1_1);
self->currentUrl = urlProvider();
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(NULL, (CFStringRef)@"GET", (__bridge CFURLRef)self->currentUrl, kCFHTTPVersion1_1);
if (seekStart > 0)
{
@@ -206,6 +235,8 @@
{
CFRelease(message);
[self errorOccured];
return;
}
@@ -213,6 +244,8 @@
{
CFRelease(message);
[self errorOccured];
return;
}
@@ -224,7 +257,7 @@
// SSL support
if ([url.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame)
if ([self->currentUrl.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame)
{
NSDictionary* sslSettings = [NSDictionary dictionaryWithObjectsAndKeys:
(NSString*)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel,
@@ -245,6 +278,8 @@
CFRelease(stream);
CFRelease(message);
[self errorOccured];
return;
}
@@ -34,18 +34,10 @@
#import "STKCoreFoundationDataSource.h"
@interface LocalFileDataSource : STKCoreFoundationDataSource
{
@private
long long position;
long long length;
AudioFileTypeID audioFileTypeHint;
}
@interface STKLocalFileDataSource : STKCoreFoundationDataSource
+(AudioFileTypeID) audioFileTypeHintFromFileExtension:(NSString*)fileExtension;
@property (readonly, copy) NSString* filePath;
-(id) initWithFilePath:(NSString*)filePath;
@end
@@ -34,13 +34,17 @@
#import "STKLocalFileDataSource.h"
@interface LocalFileDataSource()
@interface STKLocalFileDataSource()
{
long long position;
long long length;
AudioFileTypeID audioFileTypeHint;
}
@property (readwrite, copy) NSString* filePath;
-(void) open;
@end
@implementation LocalFileDataSource
@implementation STKLocalFileDataSource
@synthesize filePath;
-(id) initWithFilePath:(NSString*)filePathIn
@@ -51,7 +55,7 @@
[self open];
audioFileTypeHint = [LocalFileDataSource audioFileTypeHintFromFileExtension:filePathIn.pathExtension];
audioFileTypeHint = [STKLocalFileDataSource audioFileTypeHintFromFileExtension:filePathIn.pathExtension];
}
return self;
@@ -111,8 +115,6 @@
-(void) open
{
NSURL* url = [[NSURL alloc] initFileURLWithPath:self.filePath];
if (stream)
{
CFReadStreamClose(stream);
@@ -121,16 +123,13 @@
stream = 0;
}
NSURL* url = [[NSURL alloc] initFileURLWithPath:self.filePath];
stream = CFReadStreamCreateWithFile(NULL, (__bridge CFURLRef)url);
NSError *fileError;
NSFileManager *manager = [[NSFileManager alloc] init];
NSString *path = [NSString stringWithUTF8String:[url fileSystemRepresentation]];
NSDictionary *attributes = [manager attributesOfItemAtPath:path
error:&fileError];
NSError* fileError;
NSFileManager* manager = [[NSFileManager alloc] init];
NSDictionary* attributes = [manager attributesOfItemAtPath:filePath error:&fileError];
if (fileError)
{
@@ -141,7 +140,6 @@
}
NSNumber* number = [attributes objectForKey:@"NSFileSize"];
if (number)
{