Added AutoRecoveringHttpDataSource
This commit is contained in:
parent
1f3c8eca52
commit
d9d1d86f31
|
|
@ -7,6 +7,10 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
A16CB9AD162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A16CB9AA162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.m */; };
|
||||||
|
A16CB9AE162EC4AB00CFD1E8 /* DataSourceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = A16CB9AC162EC4AB00CFD1E8 /* DataSourceWrapper.m */; };
|
||||||
|
A16CB9B1162EC5E300CFD1E8 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A16CB9B0162EC5E300CFD1E8 /* SystemConfiguration.framework */; };
|
||||||
|
A16CB9B3162EC5E900CFD1E8 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A16CB9B2162EC5E900CFD1E8 /* Default-568h@2x.png */; };
|
||||||
A186B4E4157F80E700BD0084 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A186B4E3157F80E700BD0084 /* UIKit.framework */; };
|
A186B4E4157F80E700BD0084 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A186B4E3157F80E700BD0084 /* UIKit.framework */; };
|
||||||
A186B4E6157F80E700BD0084 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A186B4E5157F80E700BD0084 /* Foundation.framework */; };
|
A186B4E6157F80E700BD0084 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A186B4E5157F80E700BD0084 /* Foundation.framework */; };
|
||||||
A186B4EE157F80E700BD0084 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A186B4EC157F80E700BD0084 /* InfoPlist.strings */; };
|
A186B4EE157F80E700BD0084 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A186B4EC157F80E700BD0084 /* InfoPlist.strings */; };
|
||||||
|
|
@ -25,6 +29,12 @@
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
A16CB9A9162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoRecoveringHttpDataSource.h; sourceTree = "<group>"; };
|
||||||
|
A16CB9AA162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoRecoveringHttpDataSource.m; sourceTree = "<group>"; };
|
||||||
|
A16CB9AB162EC4AB00CFD1E8 /* DataSourceWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataSourceWrapper.h; sourceTree = "<group>"; };
|
||||||
|
A16CB9AC162EC4AB00CFD1E8 /* DataSourceWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DataSourceWrapper.m; sourceTree = "<group>"; };
|
||||||
|
A16CB9B0162EC5E300CFD1E8 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||||
|
A16CB9B2162EC5E900CFD1E8 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../Default-568h@2x.png"; sourceTree = "<group>"; };
|
||||||
A186B4DF157F80E600BD0084 /* Audjustable.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Audjustable.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
A186B4DF157F80E600BD0084 /* Audjustable.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Audjustable.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
A186B4E3157F80E700BD0084 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
A186B4E3157F80E700BD0084 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||||
A186B4E5157F80E700BD0084 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
A186B4E5157F80E700BD0084 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||||
|
|
@ -58,6 +68,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
A16CB9B1162EC5E300CFD1E8 /* SystemConfiguration.framework in Frameworks */,
|
||||||
A186B51A157F819500BD0084 /* CFNetwork.framework in Frameworks */,
|
A186B51A157F819500BD0084 /* CFNetwork.framework in Frameworks */,
|
||||||
A186B518157F818900BD0084 /* CoreFoundation.framework in Frameworks */,
|
A186B518157F818900BD0084 /* CoreFoundation.framework in Frameworks */,
|
||||||
A186B514157F817500BD0084 /* AudioToolbox.framework in Frameworks */,
|
A186B514157F817500BD0084 /* AudioToolbox.framework in Frameworks */,
|
||||||
|
|
@ -72,6 +83,7 @@
|
||||||
A186B4D4157F80E600BD0084 = {
|
A186B4D4157F80E600BD0084 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
A16CB9B0162EC5E300CFD1E8 /* SystemConfiguration.framework */,
|
||||||
A186B4E9157F80E700BD0084 /* Audjustable */,
|
A186B4E9157F80E700BD0084 /* Audjustable */,
|
||||||
A186B4E2157F80E700BD0084 /* Frameworks */,
|
A186B4E2157F80E700BD0084 /* Frameworks */,
|
||||||
A186B4E0157F80E600BD0084 /* Products */,
|
A186B4E0157F80E600BD0084 /* Products */,
|
||||||
|
|
@ -116,6 +128,7 @@
|
||||||
A186B51B157F81D900BD0084 /* Resources */,
|
A186B51B157F81D900BD0084 /* Resources */,
|
||||||
A186B4EB157F80E700BD0084 /* Audjustable-Info.plist */,
|
A186B4EB157F80E700BD0084 /* Audjustable-Info.plist */,
|
||||||
A186B4EC157F80E700BD0084 /* InfoPlist.strings */,
|
A186B4EC157F80E700BD0084 /* InfoPlist.strings */,
|
||||||
|
A16CB9B2162EC5E900CFD1E8 /* Default-568h@2x.png */,
|
||||||
A186B4EF157F80E700BD0084 /* main.m */,
|
A186B4EF157F80E700BD0084 /* main.m */,
|
||||||
A186B4F1157F80E700BD0084 /* Audjustable-Prefix.pch */,
|
A186B4F1157F80E700BD0084 /* Audjustable-Prefix.pch */,
|
||||||
);
|
);
|
||||||
|
|
@ -135,6 +148,10 @@
|
||||||
A186B4FF157F813100BD0084 /* AudioPlayer */ = {
|
A186B4FF157F813100BD0084 /* AudioPlayer */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
A16CB9A9162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.h */,
|
||||||
|
A16CB9AA162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.m */,
|
||||||
|
A16CB9AB162EC4AB00CFD1E8 /* DataSourceWrapper.h */,
|
||||||
|
A16CB9AC162EC4AB00CFD1E8 /* DataSourceWrapper.m */,
|
||||||
A186B500157F813100BD0084 /* AudioPlayer.h */,
|
A186B500157F813100BD0084 /* AudioPlayer.h */,
|
||||||
A186B501157F813100BD0084 /* AudioPlayer.m */,
|
A186B501157F813100BD0084 /* AudioPlayer.m */,
|
||||||
A186B502157F813100BD0084 /* CoreFoundationDataSource.h */,
|
A186B502157F813100BD0084 /* CoreFoundationDataSource.h */,
|
||||||
|
|
@ -209,6 +226,7 @@
|
||||||
files = (
|
files = (
|
||||||
A186B4EE157F80E700BD0084 /* InfoPlist.strings in Resources */,
|
A186B4EE157F80E700BD0084 /* InfoPlist.strings in Resources */,
|
||||||
A186B51D157F825400BD0084 /* sample.m4a in Resources */,
|
A186B51D157F825400BD0084 /* sample.m4a in Resources */,
|
||||||
|
A16CB9B3162EC5E900CFD1E8 /* Default-568h@2x.png in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -227,6 +245,8 @@
|
||||||
A186B50F157F813100BD0084 /* HttpDataSource.m in Sources */,
|
A186B50F157F813100BD0084 /* HttpDataSource.m in Sources */,
|
||||||
A186B510157F813100BD0084 /* LocalFileDataSource.m in Sources */,
|
A186B510157F813100BD0084 /* LocalFileDataSource.m in Sources */,
|
||||||
A186B511157F813100BD0084 /* AudioPlayerView.m in Sources */,
|
A186B511157F813100BD0084 /* AudioPlayerView.m in Sources */,
|
||||||
|
A16CB9AD162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.m in Sources */,
|
||||||
|
A16CB9AE162EC4AB00CFD1E8 /* DataSourceWrapper.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:Audjustable.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
BIN
Audjustable.xcodeproj/project.xcworkspace/xcuserdata/tum.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
Audjustable.xcodeproj/project.xcworkspace/xcuserdata/tum.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "0450"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "A186B4DE157F80E600BD0084"
|
||||||
|
BuildableName = "Audjustable.app"
|
||||||
|
BlueprintName = "Audjustable"
|
||||||
|
ReferencedContainer = "container:Audjustable.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "A186B4DE157F80E600BD0084"
|
||||||
|
BuildableName = "Audjustable.app"
|
||||||
|
BlueprintName = "Audjustable"
|
||||||
|
ReferencedContainer = "container:Audjustable.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "A186B4DE157F80E600BD0084"
|
||||||
|
BuildableName = "Audjustable.app"
|
||||||
|
BlueprintName = "Audjustable"
|
||||||
|
ReferencedContainer = "container:Audjustable.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "A186B4DE157F80E600BD0084"
|
||||||
|
BuildableName = "Audjustable.app"
|
||||||
|
BlueprintName = "Audjustable"
|
||||||
|
ReferencedContainer = "container:Audjustable.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?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>SchemeUserState</key>
|
||||||
|
<dict>
|
||||||
|
<key>Audjustable.xcscheme</key>
|
||||||
|
<dict>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>SuppressBuildableAutocreation</key>
|
||||||
|
<dict>
|
||||||
|
<key>A186B4DE157F80E600BD0084</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
Binary file not shown.
|
|
@ -103,6 +103,7 @@ AudioPlayerErrorCode;
|
||||||
-(void) audioPlayer:(AudioPlayer*)audioPlayer didFinishPlayingQueueItemId:(NSObject*)queueItemId withReason:(AudioPlayerStopReason)stopReason andProgress:(double)progress andDuration:(double)duration;
|
-(void) audioPlayer:(AudioPlayer*)audioPlayer didFinishPlayingQueueItemId:(NSObject*)queueItemId withReason:(AudioPlayerStopReason)stopReason andProgress:(double)progress andDuration:(double)duration;
|
||||||
@optional
|
@optional
|
||||||
-(void) audioPlayer:(AudioPlayer*)audioPlayer internalStateChanged:(AudioPlayerInternalState)state;
|
-(void) audioPlayer:(AudioPlayer*)audioPlayer internalStateChanged:(AudioPlayerInternalState)state;
|
||||||
|
-(void) audioPlayer:(AudioPlayer*)audioPlayer didCancelQueuedItems:(NSArray*)queuedItems;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@class QueueEntry;
|
@class QueueEntry;
|
||||||
|
|
|
||||||
|
|
@ -468,7 +468,34 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||||
{
|
{
|
||||||
@synchronized(self)
|
@synchronized(self)
|
||||||
{
|
{
|
||||||
|
NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity:bufferingQueue.count + upcomingQueue.count];
|
||||||
|
|
||||||
|
QueueEntry* entry = [bufferingQueue dequeue];
|
||||||
|
|
||||||
|
if (entry && entry != currentlyPlayingEntry)
|
||||||
|
{
|
||||||
|
[array addObject:[entry queueItemId]];
|
||||||
|
}
|
||||||
|
|
||||||
|
while (bufferingQueue.count > 0)
|
||||||
|
{
|
||||||
|
[array addObject:[[bufferingQueue dequeue] queueItemId]];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (QueueEntry* entry in upcomingQueue)
|
||||||
|
{
|
||||||
|
[array addObject:entry.queueItemId];
|
||||||
|
}
|
||||||
|
|
||||||
[upcomingQueue removeAllObjects];
|
[upcomingQueue removeAllObjects];
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^
|
||||||
|
{
|
||||||
|
if ([self.delegate respondsToSelector:@selector(audioPlayer:didCancelQueuedItems:)])
|
||||||
|
{
|
||||||
|
[self.delegate audioPlayer:self didCancelQueuedItems:array];
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1258,13 +1285,18 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||||
currentlyReadingEntry.dataSource.delegate = nil;
|
currentlyReadingEntry.dataSource.delegate = nil;
|
||||||
[currentlyReadingEntry.dataSource unregisterForEvents];
|
[currentlyReadingEntry.dataSource unregisterForEvents];
|
||||||
|
|
||||||
if (currentlyReadingEntry)
|
if (currentlyPlayingEntry)
|
||||||
{
|
{
|
||||||
[self processDidFinishPlaying:currentlyPlayingEntry withNext:nil];
|
[self processDidFinishPlaying:currentlyPlayingEntry withNext:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&queueBuffersMutex);
|
pthread_mutex_lock(&queueBuffersMutex);
|
||||||
|
|
||||||
|
if ([bufferingQueue peek] == currentlyPlayingEntry)
|
||||||
|
{
|
||||||
|
[bufferingQueue dequeue];
|
||||||
|
}
|
||||||
|
|
||||||
currentlyPlayingEntry = nil;
|
currentlyPlayingEntry = nil;
|
||||||
currentlyReadingEntry = nil;
|
currentlyReadingEntry = nil;
|
||||||
seekToTimeWasRequested = NO;
|
seekToTimeWasRequested = NO;
|
||||||
|
|
@ -1276,15 +1308,20 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ
|
||||||
currentlyReadingEntry.dataSource.delegate = nil;
|
currentlyReadingEntry.dataSource.delegate = nil;
|
||||||
[currentlyReadingEntry.dataSource unregisterForEvents];
|
[currentlyReadingEntry.dataSource unregisterForEvents];
|
||||||
|
|
||||||
if (currentlyReadingEntry)
|
if (currentlyPlayingEntry)
|
||||||
{
|
{
|
||||||
[self processDidFinishPlaying:currentlyPlayingEntry withNext:nil];
|
[self processDidFinishPlaying:currentlyPlayingEntry withNext:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&queueBuffersMutex);
|
pthread_mutex_lock(&queueBuffersMutex);
|
||||||
|
|
||||||
|
if ([bufferingQueue peek] == currentlyPlayingEntry)
|
||||||
|
{
|
||||||
|
[bufferingQueue dequeue];
|
||||||
|
}
|
||||||
|
|
||||||
currentlyPlayingEntry = nil;
|
currentlyPlayingEntry = nil;
|
||||||
currentlyReadingEntry = nil;
|
currentlyReadingEntry = nil;
|
||||||
|
|
||||||
pthread_mutex_unlock(&queueBuffersMutex);
|
pthread_mutex_unlock(&queueBuffersMutex);
|
||||||
|
|
||||||
[self resetAudioQueue];
|
[self resetAudioQueue];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
//
|
||||||
|
// AutoRecoveringHttpDataSource.h
|
||||||
|
// bloom
|
||||||
|
//
|
||||||
|
// Created by Thong Nguyen on 16/10/2012.
|
||||||
|
// Copyright (c) 2012 DDN Ltd. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "DataSource.h"
|
||||||
|
#import "HttpDataSource.h"
|
||||||
|
#import "DataSourceWrapper.h"
|
||||||
|
|
||||||
|
@interface AutoRecoveringHttpDataSource : DataSourceWrapper
|
||||||
|
|
||||||
|
-(id) initWithHttpDataSource:(HttpDataSource*)innerDataSource;
|
||||||
|
|
||||||
|
@property (readonly) HttpDataSource* innerDataSource;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
//
|
||||||
|
// AutoRecoveringHttpDataSource.m
|
||||||
|
// bloom
|
||||||
|
//
|
||||||
|
// Created by Thong Nguyen on 16/10/2012.
|
||||||
|
// Copyright (c) 2012 DDN Ltd. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <sys/socket.h>
|
||||||
|
#import <netinet/in.h>
|
||||||
|
#import <netinet6/in6.h>
|
||||||
|
#import <arpa/inet.h>
|
||||||
|
#import <ifaddrs.h>
|
||||||
|
#import <netdb.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <SystemConfiguration/SystemConfiguration.h>
|
||||||
|
#import "AutoRecoveringHttpDataSource.h"
|
||||||
|
|
||||||
|
#define MAX_IMMEDIATE_RECONNECT_ATTEMPTS (8)
|
||||||
|
|
||||||
|
@interface AutoRecoveringHttpDataSource()
|
||||||
|
{
|
||||||
|
int reconnectAttempts;
|
||||||
|
BOOL waitingForNetwork;
|
||||||
|
SCNetworkReachabilityRef reachabilityRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) reachabilityChanged;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
|
||||||
|
{
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
AutoRecoveringHttpDataSource* dataSource = (__bridge AutoRecoveringHttpDataSource*)info;
|
||||||
|
|
||||||
|
[dataSource reachabilityChanged];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation AutoRecoveringHttpDataSource
|
||||||
|
|
||||||
|
-(HttpDataSource*) innerHttpDataSource
|
||||||
|
{
|
||||||
|
return (HttpDataSource*)self.innerDataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(id) initWithHttpDataSource:(HttpDataSource*)innerDataSourceIn
|
||||||
|
{
|
||||||
|
if (self = [super initWithDataSource:innerDataSourceIn])
|
||||||
|
{
|
||||||
|
self.innerDataSource.delegate = self;
|
||||||
|
|
||||||
|
struct sockaddr_in zeroAddress;
|
||||||
|
|
||||||
|
bzero(&zeroAddress, sizeof(zeroAddress));
|
||||||
|
zeroAddress.sin_len = sizeof(zeroAddress);
|
||||||
|
zeroAddress.sin_family = AF_INET;
|
||||||
|
|
||||||
|
reachabilityRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL) startNotifierOnRunLoop:(NSRunLoop*)runLoop
|
||||||
|
{
|
||||||
|
BOOL retVal = NO;
|
||||||
|
SCNetworkReachabilityContext context = { 0, (__bridge void*)self, NULL, NULL, NULL };
|
||||||
|
|
||||||
|
if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
|
||||||
|
{
|
||||||
|
if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, runLoop.getCFRunLoop, kCFRunLoopDefaultMode))
|
||||||
|
{
|
||||||
|
retVal = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL) registerForEvents:(NSRunLoop*)runLoop
|
||||||
|
{
|
||||||
|
[super registerForEvents:runLoop];
|
||||||
|
[self startNotifierOnRunLoop:runLoop];
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) unregisterForEvents
|
||||||
|
{
|
||||||
|
[self stopNotifier];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) stopNotifier
|
||||||
|
{
|
||||||
|
if (reachabilityRef != NULL)
|
||||||
|
{
|
||||||
|
SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL) hasGotNetworkConnection
|
||||||
|
{
|
||||||
|
SCNetworkReachabilityFlags flags;
|
||||||
|
|
||||||
|
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
|
||||||
|
{
|
||||||
|
return ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) dealloc
|
||||||
|
{
|
||||||
|
[self stopNotifier];
|
||||||
|
|
||||||
|
if (reachabilityRef!= NULL)
|
||||||
|
{
|
||||||
|
CFRelease(reachabilityRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) reachabilityChanged
|
||||||
|
{
|
||||||
|
if (waitingForNetwork)
|
||||||
|
{
|
||||||
|
waitingForNetwork = NO;
|
||||||
|
|
||||||
|
[self attemptReconnect];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) dataSourceDataAvailable:(DataSource*)dataSource
|
||||||
|
{
|
||||||
|
reconnectAttempts = 0;
|
||||||
|
|
||||||
|
[super dataSourceDataAvailable:dataSource];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) attemptReconnect
|
||||||
|
{
|
||||||
|
reconnectAttempts++;
|
||||||
|
|
||||||
|
[self seekToOffset:self.position];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) dataSourceErrorOccured:(DataSource*)dataSource
|
||||||
|
{
|
||||||
|
if (![self hasGotNetworkConnection])
|
||||||
|
{
|
||||||
|
waitingForNetwork = YES;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reconnectAttempts > MAX_IMMEDIATE_RECONNECT_ATTEMPTS)
|
||||||
|
{
|
||||||
|
[self performSelector:@selector(attemptReconnect) withObject:nil afterDelay:5];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[self attemptReconnect];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
//
|
||||||
|
// DataSourceWrapper.h
|
||||||
|
// bloom
|
||||||
|
//
|
||||||
|
// Created by Thong Nguyen on 16/10/2012.
|
||||||
|
// Copyright (c) 2012 DDN Ltd. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "DataSource.h"
|
||||||
|
|
||||||
|
@interface DataSourceWrapper : DataSource<DataSourceDelegate>
|
||||||
|
|
||||||
|
-(id) initWithDataSource:(DataSource*)innerDataSource;
|
||||||
|
|
||||||
|
@property (readonly) DataSource* innerDataSource;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
//
|
||||||
|
// DataSourceWrapper.m
|
||||||
|
// bloom
|
||||||
|
//
|
||||||
|
// Created by Thong Nguyen on 16/10/2012.
|
||||||
|
// Copyright (c) 2012 DDN Ltd. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "DataSourceWrapper.h"
|
||||||
|
|
||||||
|
@interface DataSourceWrapper()
|
||||||
|
@property (readwrite) DataSource* innerDataSource;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation DataSourceWrapper
|
||||||
|
|
||||||
|
-(id) initWithDataSource:(DataSource*)innerDataSourceIn
|
||||||
|
{
|
||||||
|
if (self = [super init])
|
||||||
|
{
|
||||||
|
self.innerDataSource = innerDataSourceIn;
|
||||||
|
|
||||||
|
self.innerDataSource.delegate = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(long long) length
|
||||||
|
{
|
||||||
|
return self.innerDataSource.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) seekToOffset:(long long)offset
|
||||||
|
{
|
||||||
|
return [self.innerDataSource seekToOffset:offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size
|
||||||
|
{
|
||||||
|
return [self.innerDataSource readIntoBuffer:buffer withSize:size];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(long long) position
|
||||||
|
{
|
||||||
|
return self.innerDataSource.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL) registerForEvents:(NSRunLoop*)runLoop
|
||||||
|
{
|
||||||
|
return [self.innerDataSource registerForEvents:runLoop];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) unregisterForEvents
|
||||||
|
{
|
||||||
|
[self.innerDataSource unregisterForEvents];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) close
|
||||||
|
{
|
||||||
|
[self.innerDataSource close];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL) hasBytesAvailable
|
||||||
|
{
|
||||||
|
return self.innerDataSource.hasBytesAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) dataSourceDataAvailable:(DataSource*)dataSource
|
||||||
|
{
|
||||||
|
[self.delegate dataSourceDataAvailable:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) dataSourceErrorOccured:(DataSource*)dataSource
|
||||||
|
{
|
||||||
|
[self.delegate dataSourceErrorOccured:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) dataSourceEof:(DataSource*)dataSource
|
||||||
|
{
|
||||||
|
[self.delegate dataSourceEof:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
Loading…
Reference in New Issue