Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d76c1c2160 | |||
| 8e90aed1a1 | |||
| 4a38a20c3a | |||
| 4a37599866 | |||
| d5e7f986ac | |||
| 6ac8851b9e | |||
| 062a320de6 | |||
| 05f50e11d0 | |||
| c213f8809a | |||
| 5baa7a07c2 | |||
| 01629e7fdf | |||
| 1283cb31cc | |||
| 1a0b463a32 | |||
| aeb1ee1b7c | |||
| ec8b82b28f | |||
| c84db3bcab | |||
| cf14a035f6 | |||
| 8da9ea9545 | |||
| ee387dc098 | |||
| c2d5d4000d | |||
| 65c1715269 | |||
| 05965388cc | |||
| ba4e44b8a2 |
@@ -0,0 +1,13 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "Audjustable"
|
||||
s.version = "0.0.0"
|
||||
s.summary = "A fast and extensible audio streamer for iOS and OSX with support for gapless playback and custom (non-HTTP) sources."
|
||||
s.homepage = "http://tumtumtum.github.com/audjustable/"
|
||||
s.license = 'MIT'
|
||||
s.author = { "Thong Nguyen" => "tumtumtum@gmail.com" }
|
||||
s.source = { :git => "https://github.com/tumtumtum/audjustable.git"}
|
||||
s.platform = :ios
|
||||
s.requires_arc = true
|
||||
s.source_files = 'Audjustable/Classes/AudioPlayer/*.{h,m}'
|
||||
s.frameworks = 'AVFoundation', 'SystemConfiguration', 'CFNetwork', 'CoreFoundation', 'AudioToolbox'
|
||||
end
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "Audjustable"
|
||||
s.version = "0.0.5"
|
||||
s.version = "0.0.9"
|
||||
s.summary = "A fast and extensible audio streamer for iOS and OSX with support for gapless playback and custom (non-HTTP) sources."
|
||||
s.homepage = "http://tumtumtum.github.com/audjustable/"
|
||||
s.license = 'MIT'
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
A186B4F2157F80E700BD0084 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
A186B4F3157F80E700BD0084 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
A186B500157F813100BD0084 /* AudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioPlayer.h; sourceTree = "<group>"; };
|
||||
A186B501157F813100BD0084 /* AudioPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioPlayer.m; sourceTree = "<group>"; };
|
||||
A186B501157F813100BD0084 /* AudioPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioPlayer.m; sourceTree = "<group>"; wrapsLines = 1; };
|
||||
A186B502157F813100BD0084 /* CoreFoundationDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreFoundationDataSource.h; sourceTree = "<group>"; };
|
||||
A186B503157F813100BD0084 /* CoreFoundationDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreFoundationDataSource.m; sourceTree = "<group>"; };
|
||||
A186B504157F813100BD0084 /* DataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataSource.h; sourceTree = "<group>"; };
|
||||
@@ -247,7 +247,7 @@
|
||||
A186B4D6157F80E600BD0084 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0460;
|
||||
LastUpgradeCheck = 0500;
|
||||
};
|
||||
buildConfigurationList = A186B4D9157F80E600BD0084 /* Build configuration list for PBXProject "Audjustable" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
@@ -371,9 +371,10 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
@@ -388,10 +389,14 @@
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
@@ -401,9 +406,10 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
@@ -411,8 +417,11 @@
|
||||
COPY_PHASE_STRIP = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
|
||||
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
|
||||
<false/>
|
||||
<key>IDESourceControlProjectIdentifier</key>
|
||||
<string>0082CB9A-521A-4A1D-A18C-AEBEDF2DF227</string>
|
||||
<key>IDESourceControlProjectName</key>
|
||||
<string>Audjustable</string>
|
||||
<key>IDESourceControlProjectOriginsDictionary</key>
|
||||
<dict>
|
||||
<key>39F64986-79A8-40D3-9B3C-3C7711576969</key>
|
||||
<string>https://github.com/tumtumtum/audjustable.git</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectPath</key>
|
||||
<string>Audjustable.xcodeproj/project.xcworkspace</string>
|
||||
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
|
||||
<dict>
|
||||
<key>39F64986-79A8-40D3-9B3C-3C7711576969</key>
|
||||
<string>../..</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectURL</key>
|
||||
<string>https://github.com/tumtumtum/audjustable.git</string>
|
||||
<key>IDESourceControlProjectVersion</key>
|
||||
<integer>110</integer>
|
||||
<key>IDESourceControlProjectWCCIdentifier</key>
|
||||
<string>39F64986-79A8-40D3-9B3C-3C7711576969</string>
|
||||
<key>IDESourceControlProjectWCConfigurations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
|
||||
<string>public.vcs.git</string>
|
||||
<key>IDESourceControlWCCIdentifierKey</key>
|
||||
<string>39F64986-79A8-40D3-9B3C-3C7711576969</string>
|
||||
<key>IDESourceControlWCCName</key>
|
||||
<string>audjustable</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0460"
|
||||
LastUpgradeVersion = "0500"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0460"
|
||||
LastUpgradeVersion = "0500"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
@@ -103,6 +103,7 @@ AudioPlayerErrorCode;
|
||||
-(void) audioPlayer:(AudioPlayer*)audioPlayer didFinishBufferingSourceWithQueueItemId:(NSObject*)queueItemId;
|
||||
-(void) audioPlayer:(AudioPlayer*)audioPlayer didFinishPlayingQueueItemId:(NSObject*)queueItemId withReason:(AudioPlayerStopReason)stopReason andProgress:(double)progress andDuration:(double)duration;
|
||||
@optional
|
||||
-(void) audioPlayer:(AudioPlayer*)audioPlayer logInfo:(NSString*)line;
|
||||
-(void) audioPlayer:(AudioPlayer*)audioPlayer internalStateChanged:(AudioPlayerInternalState)state;
|
||||
-(void) audioPlayer:(AudioPlayer*)audioPlayer didCancelQueuedItems:(NSArray*)queuedItems;
|
||||
@end
|
||||
@@ -172,6 +173,10 @@ AudioQueueBufferRefLookupEntry;
|
||||
volatile BOOL audioQueueFlushing;
|
||||
volatile SInt64 audioPacketsReadCount;
|
||||
volatile SInt64 audioPacketsPlayedCount;
|
||||
|
||||
BOOL meteringEnabled;
|
||||
AudioQueueLevelMeterState* levelMeterState;
|
||||
NSInteger numberOfChannels;
|
||||
}
|
||||
|
||||
@property (readonly) double duration;
|
||||
@@ -179,6 +184,7 @@ AudioQueueBufferRefLookupEntry;
|
||||
@property (readwrite) AudioPlayerState state;
|
||||
@property (readonly) AudioPlayerStopReason stopReason;
|
||||
@property (readwrite, unsafe_unretained) id<AudioPlayerDelegate> delegate;
|
||||
@property (readwrite) BOOL meteringEnabled;
|
||||
|
||||
-(id) init;
|
||||
-(id) initWithNumberOfAudioQueueBuffers:(int)numberOfAudioQueueBuffers andReadBufferSize:(int)readBufferSizeIn;
|
||||
@@ -191,7 +197,12 @@ AudioQueueBufferRefLookupEntry;
|
||||
-(void) resume;
|
||||
-(void) stop;
|
||||
-(void) flushStop;
|
||||
-(void) mute;
|
||||
-(void) unmute;
|
||||
-(void) dispose;
|
||||
-(NSObject*) currentlyPlayingQueueItemId;
|
||||
-(void) updateMeters;
|
||||
-(float) peakPowerInDecibelsForChannel:(NSUInteger)channelNumber;
|
||||
-(float) averagePowerInDecibelsForChannel:(NSUInteger)channelNumber;
|
||||
|
||||
@end
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
@@ -48,12 +48,6 @@
|
||||
|
||||
#define OSSTATUS_PARAM_ERROR (-50)
|
||||
|
||||
#define SPIN_LOCK_LOCK(x) \
|
||||
while(OSAtomicCompareAndSwapInt(0, 1, x) == false);
|
||||
|
||||
#define SPIN_LOCK_UNLOCK(x) \
|
||||
*x = 0;
|
||||
|
||||
@interface NSMutableArray(AudioPlayerExtensions)
|
||||
-(void) enqueue:(id)obj;
|
||||
-(id) dequeue;
|
||||
@@ -219,7 +213,7 @@
|
||||
|
||||
double calculatedBitRate = [self calculatedBitRate];
|
||||
|
||||
if (calculatedBitRate == 0 || self->dataSource.length == 0)
|
||||
if (calculatedBitRate == 0 || dataSource.length == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -254,12 +248,13 @@
|
||||
@interface AudioPlayer()
|
||||
@property (readwrite) AudioPlayerInternalState internalState;
|
||||
|
||||
-(void) logInfo:(NSString*)line;
|
||||
-(void) processQueue:(BOOL)skipCurrent;
|
||||
-(void) createAudioQueue;
|
||||
-(void) enqueueBuffer;
|
||||
-(void) resetAudioQueue;
|
||||
-(void) resetAudioQueueWithReason:(NSString*)reason;
|
||||
-(BOOL) startAudioQueue;
|
||||
-(void) stopAudioQueue;
|
||||
-(void) stopAudioQueueWithReason:(NSString*)reason;
|
||||
-(BOOL) processRunloop;
|
||||
-(void) wakeupPlaybackThread;
|
||||
-(void) audioQueueFinishedPlaying:(QueueEntry*)entry;
|
||||
@@ -321,9 +316,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;
|
||||
@@ -382,6 +377,14 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
return isRunning ? YES : NO;
|
||||
}
|
||||
|
||||
-(void) logInfo:(NSString*)line
|
||||
{
|
||||
if ([self->delegate respondsToSelector:@selector(audioPlayer:logInfo:)])
|
||||
{
|
||||
[self->delegate audioPlayer:self logInfo:line];
|
||||
}
|
||||
}
|
||||
|
||||
-(id) init
|
||||
{
|
||||
return [self initWithNumberOfAudioQueueBuffers:AudioPlayerDefaultNumberOfAudioQueueBuffers andReadBufferSize:AudioPlayerDefaultReadBufferSize];
|
||||
@@ -393,7 +396,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
{
|
||||
fastApiQueue = [[NSOperationQueue alloc] init];
|
||||
[fastApiQueue setMaxConcurrentOperationCount:1];
|
||||
|
||||
|
||||
readBufferSize = readBufferSizeIn;
|
||||
readBuffer = calloc(sizeof(UInt8), readBufferSize);
|
||||
|
||||
@@ -457,6 +460,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
free(packetDescs);
|
||||
free(audioQueueBuffer);
|
||||
free(audioQueueBufferLookup);
|
||||
free(levelMeterState);
|
||||
}
|
||||
|
||||
-(void) startSystemBackgroundTask
|
||||
@@ -534,12 +538,12 @@ 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);
|
||||
}
|
||||
@@ -554,34 +558,34 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
[fastApiQueue cancelAllOperations];
|
||||
|
||||
[fastApiQueue addOperationWithBlock:^
|
||||
{
|
||||
pthread_mutex_lock(&playerMutex);
|
||||
{
|
||||
[self startSystemBackgroundTask];
|
||||
|
||||
[self clearQueue];
|
||||
|
||||
[upcomingQueue enqueue:[[QueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]];
|
||||
|
||||
self.internalState = AudioPlayerInternalStateRunning;
|
||||
[self processQueue:YES];
|
||||
}
|
||||
pthread_mutex_unlock(&playerMutex);
|
||||
}];
|
||||
{
|
||||
pthread_mutex_lock(&playerMutex);
|
||||
{
|
||||
[self startSystemBackgroundTask];
|
||||
|
||||
[self clearQueue];
|
||||
|
||||
[upcomingQueue enqueue:[[QueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]];
|
||||
|
||||
self.internalState = AudioPlayerInternalStateRunning;
|
||||
[self processQueue:YES];
|
||||
}
|
||||
pthread_mutex_unlock(&playerMutex);
|
||||
}];
|
||||
}
|
||||
|
||||
-(void) queueDataSource:(DataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId
|
||||
{
|
||||
[fastApiQueue addOperationWithBlock:^
|
||||
{
|
||||
pthread_mutex_lock(&playerMutex);
|
||||
{
|
||||
[upcomingQueue enqueue:[[QueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]];
|
||||
|
||||
[self processQueue:NO];
|
||||
}
|
||||
pthread_mutex_unlock(&playerMutex);
|
||||
}];
|
||||
{
|
||||
pthread_mutex_lock(&playerMutex);
|
||||
{
|
||||
[upcomingQueue enqueue:[[QueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]];
|
||||
|
||||
[self processQueue:NO];
|
||||
}
|
||||
pthread_mutex_unlock(&playerMutex);
|
||||
}];
|
||||
}
|
||||
|
||||
-(void) handlePropertyChangeForFileStream:(AudioFileStreamID)inAudioFileStream fileStreamPropertyID:(AudioFileStreamPropertyID)inPropertyID ioFlags:(UInt32*)ioFlags
|
||||
@@ -608,7 +612,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
if (currentlyReadingEntry->audioStreamBasicDescription.mSampleRate == 0) {
|
||||
AudioStreamBasicDescription newBasicDescription;
|
||||
UInt32 size = sizeof(newBasicDescription);
|
||||
|
||||
|
||||
AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat, &size, &newBasicDescription);
|
||||
currentlyReadingEntry->audioStreamBasicDescription = newBasicDescription;
|
||||
}
|
||||
@@ -662,7 +666,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
AudioFormatListItem *formatList = malloc(formatListSize);
|
||||
err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_FormatList, &formatListSize, formatList);
|
||||
if (err)
|
||||
@@ -670,11 +674,11 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
free(formatList);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i * sizeof(AudioFormatListItem) < formatListSize; i += sizeof(AudioFormatListItem))
|
||||
{
|
||||
AudioStreamBasicDescription pasbd = formatList[i].mASBD;
|
||||
|
||||
|
||||
if (pasbd.mFormatID == kAudioFormatMPEG4AAC_HE ||
|
||||
pasbd.mFormatID == kAudioFormatMPEG4AAC_HE_V2)
|
||||
{
|
||||
@@ -739,7 +743,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
|
||||
if (currentlyReadingEntry->processedPacketsSizeTotal < 0xfffff)
|
||||
{
|
||||
OSAtomicAdd32(packetSize, ¤tlyReadingEntry->processedPacketsSizeTotal);
|
||||
OSAtomicAdd32((int32_t)packetSize, ¤tlyReadingEntry->processedPacketsSizeTotal);
|
||||
OSAtomicIncrement32(¤tlyReadingEntry->processedPacketsCount);
|
||||
}
|
||||
|
||||
@@ -854,7 +858,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
|
||||
if (currentlyPlayingEntry)
|
||||
{
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
{
|
||||
if (currentlyPlayingEntry)
|
||||
{
|
||||
@@ -866,7 +870,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
}
|
||||
}
|
||||
}
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
}
|
||||
|
||||
int index = (int)bufferIn % audioQueueBufferRefLookupCount;
|
||||
@@ -915,7 +919,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
if (!audioQueueFlushing && [self progress] > 4.0 && numberOfBuffersUsed == 0 ) {
|
||||
self.internalState = AudioPlayerInternalStateRebuffering;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!audioQueueFlushing)
|
||||
{
|
||||
@@ -928,9 +932,9 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
if (playbackThread)
|
||||
{
|
||||
CFRunLoopPerformBlock([playbackThreadRunLoop getCFRunLoop], NSDefaultRunLoopMode, ^
|
||||
{
|
||||
[self audioQueueFinishedPlaying:entry];
|
||||
});
|
||||
{
|
||||
[self audioQueueFinishedPlaying:entry];
|
||||
});
|
||||
|
||||
CFRunLoopWakeUp([playbackThreadRunLoop getCFRunLoop]);
|
||||
|
||||
@@ -939,7 +943,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (self.internalState == AudioPlayerInternalStateStopped
|
||||
|| self.internalState == AudioPlayerInternalStateStopping
|
||||
|| self.internalState == AudioPlayerInternalStateDisposed
|
||||
@@ -967,7 +971,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
}
|
||||
}
|
||||
|
||||
if (signal || YES)
|
||||
if (signal)
|
||||
{
|
||||
pthread_cond_signal(&queueBufferReadyCondition);
|
||||
}
|
||||
@@ -1079,7 +1083,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
pthread_mutex_unlock(&playerMutex);
|
||||
|
||||
pthread_mutex_lock(&queueBuffersMutex);
|
||||
|
||||
|
||||
waiting = YES;
|
||||
|
||||
while (bufferUsed[fillBufferIndex] && !(seekToTimeWasRequested || self.internalState == AudioPlayerInternalStateStopped || self.internalState == AudioPlayerInternalStateStopping || self.internalState == AudioPlayerInternalStateDisposed))
|
||||
@@ -1103,6 +1107,11 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
{
|
||||
errorCode = errorCodeIn;
|
||||
self.internalState = AudioPlayerInternalStateError;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self.delegate audioPlayer:self didEncounterError:errorCode];
|
||||
});
|
||||
}
|
||||
|
||||
-(void) createAudioQueue
|
||||
@@ -1119,9 +1128,9 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
audioQueue = nil;
|
||||
}
|
||||
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
currentAudioStreamBasicDescription = currentlyPlayingEntry->audioStreamBasicDescription;
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
error = AudioQueueNewOutput(¤tlyPlayingEntry->audioStreamBasicDescription, AudioQueueOutputCallbackProc, (__bridge void*)self, NULL, NULL, 0, &audioQueue);
|
||||
|
||||
@@ -1216,6 +1225,10 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
|
||||
AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1);
|
||||
|
||||
// Reset metering enabled in case the user set it before the queue was created
|
||||
|
||||
[self setMeteringEnabled:meteringEnabled];
|
||||
|
||||
free(cookieData);
|
||||
}
|
||||
|
||||
@@ -1226,16 +1239,22 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
|
||||
QueueEntry* entry = currentlyPlayingEntry;
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
|
||||
if (entry == nil)
|
||||
{
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return [entry duration];
|
||||
double retval = [entry duration];
|
||||
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
-(double) progress
|
||||
@@ -1250,11 +1269,22 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
QueueEntry* entry = currentlyPlayingEntry;
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
|
||||
return [entry progress];
|
||||
QueueEntry* entry = currentlyPlayingEntry;
|
||||
|
||||
if (entry == nil)
|
||||
{
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
double retval = [entry progress];
|
||||
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
-(void) wakeupPlaybackThread
|
||||
@@ -1317,7 +1347,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
{
|
||||
newFileToPlay = YES;
|
||||
|
||||
[self resetAudioQueue];
|
||||
[self resetAudioQueueWithReason:@"from skipCurrent"];
|
||||
}
|
||||
|
||||
[self wakeupPlaybackThread];
|
||||
@@ -1334,7 +1364,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
{
|
||||
pthread_mutex_unlock(&queueBuffersMutex);
|
||||
|
||||
[self resetAudioQueue];
|
||||
[self resetAudioQueueWithReason:@"from setCurrentlyReadingEntry"];
|
||||
|
||||
pthread_mutex_lock(&queueBuffersMutex);
|
||||
}
|
||||
@@ -1361,9 +1391,9 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
{
|
||||
[currentlyReadingEntry.dataSource seekToOffset:0];
|
||||
}
|
||||
|
||||
|
||||
[currentlyReadingEntry.dataSource registerForEvents:[NSRunLoop currentRunLoop]];
|
||||
|
||||
|
||||
if (startPlaying)
|
||||
{
|
||||
[bufferingQueue removeAllObjects];
|
||||
@@ -1404,9 +1434,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
double progress = [entry progress];
|
||||
double duration = [entry duration];
|
||||
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
BOOL nextIsDifferent = currentlyPlayingEntry != next;
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
|
||||
if (next)
|
||||
{
|
||||
@@ -1417,35 +1445,33 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
seekToTimeWasRequested = NO;
|
||||
}
|
||||
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
currentlyPlayingEntry = next;
|
||||
currentlyPlayingEntry->bytesPlayed = 0;
|
||||
NSObject* playingQueueItemId = playingQueueItemId = currentlyPlayingEntry.queueItemId;
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
if (nextIsDifferent && entry)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self.delegate audioPlayer:self didFinishPlayingQueueItemId:queueItemId withReason:stopReason andProgress:progress andDuration:duration];
|
||||
});
|
||||
{
|
||||
[self.delegate audioPlayer:self didFinishPlayingQueueItemId:queueItemId withReason:stopReason andProgress:progress andDuration:duration];
|
||||
});
|
||||
}
|
||||
|
||||
if (nextIsDifferent)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self.delegate audioPlayer:self didStartPlayingQueueItemId:playingQueueItemId];
|
||||
});
|
||||
{
|
||||
[self.delegate audioPlayer:self didStartPlayingQueueItemId:playingQueueItemId];
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
{
|
||||
currentlyPlayingEntry = nil;
|
||||
}
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
currentlyPlayingEntry = nil;
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
if (currentlyReadingEntry == nil)
|
||||
{
|
||||
@@ -1496,7 +1522,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
}
|
||||
else if (self.internalState == AudioPlayerInternalStateStopped && stopReason == AudioPlayerStopReasonUserAction)
|
||||
{
|
||||
[self stopAudioQueue];
|
||||
[self stopAudioQueueWithReason:@"from processRunLoop/1"];
|
||||
|
||||
currentlyReadingEntry.dataSource.delegate = nil;
|
||||
[currentlyReadingEntry.dataSource unregisterForEvents];
|
||||
@@ -1514,11 +1540,9 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
[bufferingQueue dequeue];
|
||||
}
|
||||
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
{
|
||||
currentlyPlayingEntry = nil;
|
||||
}
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
currentlyPlayingEntry = nil;
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
currentlyReadingEntry = nil;
|
||||
seekToTimeWasRequested = NO;
|
||||
@@ -1543,16 +1567,14 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
[bufferingQueue dequeue];
|
||||
}
|
||||
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
{
|
||||
currentlyPlayingEntry = nil;
|
||||
}
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
currentlyPlayingEntry = nil;
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
currentlyReadingEntry = nil;
|
||||
pthread_mutex_unlock(&queueBuffersMutex);
|
||||
|
||||
[self resetAudioQueue];
|
||||
[self resetAudioQueueWithReason:@"from processRunLoop"];
|
||||
}
|
||||
else if (currentlyReadingEntry == nil)
|
||||
{
|
||||
@@ -1600,7 +1622,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
{
|
||||
if (self.internalState != AudioPlayerInternalStateStopped)
|
||||
{
|
||||
[self stopAudioQueue];
|
||||
[self stopAudioQueueWithReason:@"from processRunLoop/2"];
|
||||
stopReason = AudioPlayerStopReasonEof;
|
||||
}
|
||||
}
|
||||
@@ -1628,16 +1650,16 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
{
|
||||
[bufferingQueue dequeue];
|
||||
}
|
||||
|
||||
|
||||
QueueEntry* newEntry = [[QueueEntry alloc] initWithDataSource:currentlyReadingEntry.dataSource andQueueItemId:currentlyReadingEntry.queueItemId];
|
||||
|
||||
newEntry->audioStreamBasicDescription = currentlyReadingEntry->audioStreamBasicDescription;
|
||||
|
||||
[upcomingQueue skipQueue:newEntry];
|
||||
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
currentlyReadingEntry = nil;
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1658,7 +1680,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
-(void) startInternal
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
{
|
||||
playbackThreadRunLoop = [NSRunLoop currentRunLoop];
|
||||
|
||||
NSThread.currentThread.threadPriority = 1;
|
||||
@@ -1667,14 +1689,14 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
packetsFilled = 0;
|
||||
|
||||
[playbackThreadRunLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (![self processRunloop])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:10];
|
||||
[playbackThreadRunLoop runMode:NSDefaultRunLoopMode beforeDate:date];
|
||||
}
|
||||
@@ -1687,11 +1709,11 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
|
||||
currentlyReadingEntry = nil;
|
||||
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
{
|
||||
currentlyPlayingEntry = nil;
|
||||
}
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
pthread_mutex_lock(&playerMutex);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
currentlyPlayingEntry = nil;
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
pthread_mutex_unlock(&playerMutex);
|
||||
|
||||
self.internalState = AudioPlayerInternalStateDisposed;
|
||||
|
||||
@@ -1703,9 +1725,9 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
-(void) processSeekToTime
|
||||
{
|
||||
OSStatus error;
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
QueueEntry* currentEntry = currentlyReadingEntry;
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
NSAssert(currentEntry == currentlyPlayingEntry, @"playing and reading must be the same");
|
||||
|
||||
@@ -1754,7 +1776,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
|
||||
if (audioQueue)
|
||||
{
|
||||
[self resetAudioQueue];
|
||||
[self resetAudioQueueWithReason:@"from seekToTime"];
|
||||
}
|
||||
|
||||
if (currentEntry)
|
||||
@@ -1780,7 +1802,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
[self startSystemBackgroundTask];
|
||||
}
|
||||
|
||||
[self stopAudioQueue];
|
||||
[self stopAudioQueueWithReason:@"from startAudioQueue"];
|
||||
[self createAudioQueue];
|
||||
|
||||
self.internalState = AudioPlayerInternalStateWaitingForQueueToStart;
|
||||
@@ -1793,18 +1815,22 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void) stopAudioQueue
|
||||
-(void) stopAudioQueueWithReason:(NSString*)reason
|
||||
{
|
||||
OSStatus error;
|
||||
|
||||
if (!audioQueue)
|
||||
{
|
||||
[self logInfo:[@"stopAudioQueue/1 " stringByAppendingString:reason]];
|
||||
|
||||
self.internalState = AudioPlayerInternalStateStopped;
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
[self logInfo:[@"stopAudioQueue/2 " stringByAppendingString:reason]];
|
||||
|
||||
audioQueueFlushing = YES;
|
||||
|
||||
error = AudioQueueStop(audioQueue, true);
|
||||
@@ -1841,10 +1867,12 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
self.internalState = AudioPlayerInternalStateStopped;
|
||||
}
|
||||
|
||||
-(void) resetAudioQueue
|
||||
-(void) resetAudioQueueWithReason:(NSString*)reason
|
||||
{
|
||||
OSStatus error;
|
||||
|
||||
[self logInfo:[@"resetAudioQueue/1 " stringByAppendingString:reason]];
|
||||
|
||||
pthread_mutex_lock(&playerMutex);
|
||||
{
|
||||
audioQueueFlushing = YES;
|
||||
@@ -1856,14 +1884,14 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
if (error)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self didEncounterError:AudioPlayerErrorQueueStopFailed];;
|
||||
});
|
||||
{
|
||||
[self didEncounterError:AudioPlayerErrorQueueStopFailed];;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&playerMutex);
|
||||
|
||||
|
||||
pthread_mutex_lock(&queueBuffersMutex);
|
||||
|
||||
if (numberOfBuffersUsed != 0)
|
||||
@@ -1977,6 +2005,8 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
[self enqueueBuffer];
|
||||
}
|
||||
|
||||
[self logInfo:[NSString stringWithFormat:@"dataSourceEof for dataSource: %@", dataSourceIn]];
|
||||
|
||||
NSObject* queueItemId = currentlyReadingEntry.queueItemId;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
@@ -1997,6 +2027,8 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
{
|
||||
if (![self audioQueueIsRunning])
|
||||
{
|
||||
[self logInfo:@"startAudioQueue from dataSourceEof"];
|
||||
|
||||
[self startAudioQueue];
|
||||
}
|
||||
}
|
||||
@@ -2053,7 +2085,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
|
||||
if (seekToTimeWasRequested)
|
||||
{
|
||||
[self resetAudioQueue];
|
||||
[self resetAudioQueueWithReason:@"from resume"];
|
||||
}
|
||||
|
||||
error = AudioQueueStart(audioQueue, 0);
|
||||
@@ -2070,7 +2102,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
[self wakeupPlaybackThread];
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&playerMutex);
|
||||
pthread_mutex_unlock(&playerMutex);
|
||||
}
|
||||
|
||||
-(void) stop
|
||||
@@ -2135,6 +2167,16 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
}
|
||||
}
|
||||
|
||||
-(void) mute
|
||||
{
|
||||
AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 0);
|
||||
}
|
||||
|
||||
-(void) unmute
|
||||
{
|
||||
AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1);
|
||||
}
|
||||
|
||||
-(void) dispose
|
||||
{
|
||||
[self stop];
|
||||
@@ -2143,16 +2185,95 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||
|
||||
-(NSObject*) currentlyPlayingQueueItemId
|
||||
{
|
||||
SPIN_LOCK_LOCK(¤tlyPlayingLock);
|
||||
OSSpinLockLock(¤tlyPlayingLock);
|
||||
|
||||
QueueEntry* entry = currentlyPlayingEntry;
|
||||
SPIN_LOCK_UNLOCK(¤tlyPlayingLock);
|
||||
|
||||
if (entry == nil)
|
||||
{
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
return entry.queueItemId;
|
||||
NSObject* retval = entry.queueItemId;
|
||||
|
||||
OSSpinLockUnlock(¤tlyPlayingLock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#pragma mark Metering
|
||||
|
||||
-(void) setMeteringEnabled:(BOOL)value
|
||||
{
|
||||
if (!audioQueue)
|
||||
{
|
||||
meteringEnabled = value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
UInt32 on = value ? 1 : 0;
|
||||
OSStatus error = AudioQueueSetProperty(audioQueue, kAudioQueueProperty_EnableLevelMetering, &on, sizeof(on));
|
||||
|
||||
if (error)
|
||||
{
|
||||
meteringEnabled = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
meteringEnabled = YES;
|
||||
}
|
||||
}
|
||||
|
||||
-(BOOL) meteringEnabled
|
||||
{
|
||||
return meteringEnabled;
|
||||
}
|
||||
|
||||
-(void) updateMeters
|
||||
{
|
||||
if (!meteringEnabled)
|
||||
{
|
||||
NSAssert(NO, @"Metering is not enabled. Make sure to set meteringEnabled = YES.");
|
||||
}
|
||||
|
||||
NSInteger channels = currentAudioStreamBasicDescription.mChannelsPerFrame;
|
||||
|
||||
if (numberOfChannels != channels)
|
||||
{
|
||||
numberOfChannels = channels;
|
||||
|
||||
if (levelMeterState) free(levelMeterState);
|
||||
{
|
||||
levelMeterState = malloc(sizeof(AudioQueueLevelMeterState) * numberOfChannels);
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 sizeofMeters = sizeof(AudioQueueLevelMeterState) * numberOfChannels;
|
||||
|
||||
AudioQueueGetProperty(audioQueue, kAudioQueueProperty_CurrentLevelMeterDB, levelMeterState, &sizeofMeters);
|
||||
}
|
||||
|
||||
-(float) peakPowerInDecibelsForChannel:(NSUInteger)channelNumber
|
||||
{
|
||||
if (!meteringEnabled || !levelMeterState || (channelNumber > numberOfChannels))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return levelMeterState[channelNumber].mPeakPower;
|
||||
}
|
||||
|
||||
-(float) averagePowerInDecibelsForChannel:(NSUInteger)channelNumber
|
||||
{
|
||||
if (!meteringEnabled || !levelMeterState || (channelNumber > numberOfChannels))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return levelMeterState[channelNumber].mAveragePower;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
https://github.com/tumtumtum/audjustable
|
||||
|
||||
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
@@ -15,15 +15,15 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/**********************************************************************************
|
||||
AudioPlayer.m
|
||||
|
||||
|
||||
Created by Thong Nguyen on 16/10/2012.
|
||||
https://github.com/tumtumtum/audjustable
|
||||
|
||||
|
||||
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
@@ -15,12 +15,12 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
@@ -43,6 +43,7 @@
|
||||
#import "AutoRecoveringHttpDataSource.h"
|
||||
|
||||
#define MAX_IMMEDIATE_RECONNECT_ATTEMPTS (8)
|
||||
#define MAX_ATTEMPTS_WITH_SERVER_ERROR (MAX_IMMEDIATE_RECONNECT_ATTEMPTS + 2)
|
||||
|
||||
@interface AutoRecoveringHttpDataSource()
|
||||
{
|
||||
@@ -178,7 +179,7 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
|
||||
[self seekToOffset:self.position];
|
||||
}
|
||||
|
||||
-(void) dataSourceErrorOccured:(DataSource*)dataSource
|
||||
-(void) processRetryOnError
|
||||
{
|
||||
if (![self hasGotNetworkConnection])
|
||||
{
|
||||
@@ -187,7 +188,11 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
|
||||
return;
|
||||
}
|
||||
|
||||
if (reconnectAttempts > MAX_IMMEDIATE_RECONNECT_ATTEMPTS)
|
||||
if (!(self.innerDataSource.httpStatusCode >= 200 && self.innerDataSource.httpStatusCode <= 299) && reconnectAttempts >= MAX_ATTEMPTS_WITH_SERVER_ERROR)
|
||||
{
|
||||
[super dataSourceErrorOccured:self];
|
||||
}
|
||||
else if (reconnectAttempts > MAX_IMMEDIATE_RECONNECT_ATTEMPTS)
|
||||
{
|
||||
[self performSelector:@selector(attemptReconnect) withObject:nil afterDelay:5];
|
||||
}
|
||||
@@ -197,4 +202,35 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach
|
||||
}
|
||||
}
|
||||
|
||||
-(void) dataSourceEof:(DataSource*)dataSource
|
||||
{
|
||||
if ([self position] != [self length])
|
||||
{
|
||||
[self processRetryOnError];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
[self.delegate dataSourceEof:self];
|
||||
}
|
||||
|
||||
-(void) dataSourceErrorOccured:(DataSource*)dataSource
|
||||
{
|
||||
if (self.innerDataSource.httpStatusCode == 416 /* Range out of bounds */)
|
||||
{
|
||||
[super dataSourceEof:dataSource];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self processRetryOnError];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-(NSString*) description
|
||||
{
|
||||
return [NSString stringWithFormat:@"Auto-recovering HTTP data source with file length: %lld and position: %lld", self.length, self.position];
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
https://github.com/tumtumtum/audjustable
|
||||
|
||||
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
@@ -15,12 +15,12 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
https://github.com/tumtumtum/audjustable
|
||||
|
||||
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
@@ -15,12 +15,12 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
|
||||
@@ -15,22 +15,22 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**********************************************************************************/
|
||||
**********************************************************************************/
|
||||
|
||||
#import "CoreFoundationDataSource.h"
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
}
|
||||
|
||||
@property (readwrite, retain) NSURL* url;
|
||||
@property (readwrite) UInt32 httpStatusCode;
|
||||
|
||||
+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)fileExtension;
|
||||
-(id) initWithURL:(NSURL*)url;
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
@@ -105,23 +105,34 @@
|
||||
{
|
||||
if (fileLength < 0)
|
||||
{
|
||||
CFTypeRef copyPropertyMessage = CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader);
|
||||
CFTypeRef response = CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader);
|
||||
|
||||
httpHeaders = (__bridge_transfer NSDictionary*)CFHTTPMessageCopyAllHeaderFields((CFHTTPMessageRef)copyPropertyMessage);
|
||||
httpHeaders = (__bridge_transfer NSDictionary*)CFHTTPMessageCopyAllHeaderFields((CFHTTPMessageRef)response);
|
||||
|
||||
CFRelease(copyPropertyMessage);
|
||||
self.httpStatusCode = CFHTTPMessageGetResponseStatusCode((CFHTTPMessageRef)response);
|
||||
|
||||
if (seekStart == 0)
|
||||
CFRelease(response);
|
||||
|
||||
if (self.httpStatusCode == 200)
|
||||
{
|
||||
fileLength = [[httpHeaders objectForKey:@"Content-Length"] integerValue];
|
||||
if (seekStart == 0)
|
||||
{
|
||||
fileLength = [[httpHeaders objectForKey:@"Content-Length"] integerValue];
|
||||
}
|
||||
|
||||
NSString* contentType = [httpHeaders objectForKey:@"Content-Type"];
|
||||
AudioFileTypeID typeIdFromMimeType = [HttpDataSource audioFileTypeHintFromMimeType:contentType];
|
||||
|
||||
if (typeIdFromMimeType != 0)
|
||||
{
|
||||
audioFileTypeHint = typeIdFromMimeType;
|
||||
}
|
||||
}
|
||||
|
||||
NSString* contentType = [httpHeaders objectForKey:@"Content-Type"];
|
||||
AudioFileTypeID typeIdFromMimeType = [HttpDataSource audioFileTypeHintFromMimeType:contentType];
|
||||
|
||||
if (typeIdFromMimeType != 0)
|
||||
else
|
||||
{
|
||||
audioFileTypeHint = typeIdFromMimeType;
|
||||
[self errorOccured];
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +164,7 @@
|
||||
|
||||
stream = 0;
|
||||
relativePosition = 0;
|
||||
seekStart = offset;
|
||||
seekStart = (int)offset;
|
||||
|
||||
[self open];
|
||||
[self reregisterForEvents];
|
||||
@@ -233,4 +244,9 @@
|
||||
CFRelease(message);
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"HTTP data source with file length: %lld and position: %lld", self.length, self.position];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
4. Neither the name of the <organization> nor the
|
||||
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
|
||||
4. Neither the name of Thong Nguyen nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[Homepage](http://tumtumtum.github.com/audjustable)
|
||||
|
||||
Audjustable is audio streaming class for iOS and OSX. Audjustable uses CoreAudio to decompress and playback audio whilst providing a clean and simple object-oriented API.
|
||||
Audjustable is an audio streaming class for iOS and OSX. Audjustable uses CoreAudio to decompress and playback audio whilst providing a clean and simple object-oriented API.
|
||||
|
||||
The primary motivation of this project was to decouple the input (DataSource/InputStreams) from the actual player logic in order to allow advanced customizable input handling such as: HTTP streaming, encryption, auto-recovery, dynamic-buffering. Along the way other features such as gapless playback were added as the opportunity arose.
|
||||
|
||||
@@ -14,7 +14,7 @@ The primary motivation of this project was to decouple the input (DataSource/Inp
|
||||
* Mostly asynchronous API
|
||||
* Buffered and gapless playback
|
||||
* Easy to implement audio data sources (HTTP and local file system DataSources provided)
|
||||
* Easy to extend DataSource to support adaptive buffering, encryption etc
|
||||
* Easy to extend DataSource to support adaptive buffering, encryption, etc.
|
||||
* Optimised for low CPU/battery usage
|
||||
|
||||
## Usage
|
||||
@@ -23,7 +23,7 @@ Download the [source](https://github.com/tumtumtum/audjustable/zipball/master) w
|
||||
|
||||
If you would like to integrate the AudioPlayer directly into your project you only need to copy the files inside the `/Audjustable/Classes/AudioPlayer` [directory](https://github.com/tumtumtum/audjustable/tree/master/Audjustable/Classes/AudioPlayer) into your project.
|
||||
|
||||
Audjustable is also available as a [Cooapod](http://cocoapods.org/?q=audjustable).
|
||||
Audjustable is also available as a [Cocoapod](http://cocoapods.org/?q=audjustable).
|
||||
|
||||
## Code
|
||||
|
||||
@@ -36,7 +36,7 @@ There are two main classes. The `DataSource` class which is the abstract base c
|
||||
AudioPlayer* audioPlayer = [[AudioPlayer 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
|
||||
// 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:@"https://github.com/downloads/tumtumtum/audjustable/sample.m4a"] withQueueItemId:@"item1"];
|
||||
|
||||
@@ -47,4 +47,4 @@ audioPlayer.delegate = self;
|
||||
Background playback on iOS is easily added to your application by calling the `AudioSessionInitialize` in your AppDelegate.
|
||||
|
||||
### Authors and Contributors
|
||||
Copyright 2012, Thong Nguyen (@tumtumtum)
|
||||
Copyright 2012, Thong Nguyen (@tumtumtum)
|
||||
|
||||
Reference in New Issue
Block a user