├── .gitignore ├── DLGPlayer ├── DLGPlayer.h ├── DLGPlayer.m ├── DLGPlayerViewController.h ├── DLGPlayerViewController.m ├── codec │ ├── DLGPlayerAudioManager.h │ ├── DLGPlayerAudioManager.m │ ├── DLGPlayerDecoder.h │ └── DLGPlayerDecoder.m ├── common │ ├── DLGPlayerDef.h │ ├── DLGPlayerUtils.h │ └── DLGPlayerUtils.m ├── frame │ ├── DLGPlayerAudioFrame.h │ ├── DLGPlayerAudioFrame.m │ ├── DLGPlayerFrame.h │ ├── DLGPlayerFrame.m │ ├── DLGPlayerVideoFrame.h │ ├── DLGPlayerVideoFrame.m │ ├── DLGPlayerVideoRGBFrame.h │ ├── DLGPlayerVideoRGBFrame.m │ ├── DLGPlayerVideoYUVFrame.h │ └── DLGPlayerVideoYUVFrame.m ├── resource │ ├── Base.lproj │ │ └── DLGPlayerStrings.strings │ ├── DLGPlayerRGBFragmentShader.glsl │ ├── DLGPlayerRotationScaleVertexShader.glsl │ ├── DLGPlayerRotationVertexShader.glsl │ ├── DLGPlayerVertexShader.glsl │ ├── DLGPlayerYUVFragmentShader.glsl │ ├── en.lproj │ │ └── DLGPlayerStrings.strings │ └── zh-Hans.lproj │ │ └── DLGPlayerStrings.strings └── view │ ├── DLGPlayerView.h │ └── DLGPlayerView.m ├── Example ├── DLGPlayer.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── DLGPlayer.xcscmblueprint └── DLGPlayer │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Externals │ ├── CocoaAsyncSocket │ │ ├── GCDAsyncSocket.h │ │ ├── GCDAsyncSocket.m │ │ ├── GCDAsyncUdpSocket.h │ │ └── GCDAsyncUdpSocket.m │ ├── CocoaHTTPServer │ │ ├── Categories │ │ │ ├── DDData.h │ │ │ ├── DDData.m │ │ │ ├── DDNumber.h │ │ │ ├── DDNumber.m │ │ │ ├── DDRange.h │ │ │ └── DDRange.m │ │ ├── HTTPAuthenticationRequest.h │ │ ├── HTTPAuthenticationRequest.m │ │ ├── HTTPConnection.h │ │ ├── HTTPConnection.m │ │ ├── HTTPLogging.h │ │ ├── HTTPMessage.h │ │ ├── HTTPMessage.m │ │ ├── HTTPResponse.h │ │ ├── HTTPServer.h │ │ ├── HTTPServer.m │ │ ├── Mime │ │ │ ├── MultipartFormDataParser.h │ │ │ ├── MultipartFormDataParser.m │ │ │ ├── MultipartMessageHeader.h │ │ │ ├── MultipartMessageHeader.m │ │ │ ├── MultipartMessageHeaderField.h │ │ │ └── MultipartMessageHeaderField.m │ │ ├── Responses │ │ │ ├── HTTPAsyncFileResponse.h │ │ │ ├── HTTPAsyncFileResponse.m │ │ │ ├── HTTPDataResponse.h │ │ │ ├── HTTPDataResponse.m │ │ │ ├── HTTPDynamicFileResponse.h │ │ │ ├── HTTPDynamicFileResponse.m │ │ │ ├── HTTPErrorResponse.h │ │ │ ├── HTTPErrorResponse.m │ │ │ ├── HTTPFileResponse.h │ │ │ ├── HTTPFileResponse.m │ │ │ ├── HTTPRedirectResponse.h │ │ │ └── HTTPRedirectResponse.m │ │ ├── WebSocket.h │ │ └── WebSocket.m │ ├── CocoaLumberjack │ │ ├── DDASLLogger.h │ │ ├── DDASLLogger.m │ │ ├── DDAbstractDatabaseLogger.h │ │ ├── DDAbstractDatabaseLogger.m │ │ ├── DDFileLogger.h │ │ ├── DDFileLogger.m │ │ ├── DDLog+LOGV.h │ │ ├── DDLog.h │ │ ├── DDLog.m │ │ ├── DDTTYLogger.h │ │ ├── DDTTYLogger.m │ │ └── Extensions │ │ │ ├── DDContextFilterLogFormatter.h │ │ │ ├── DDContextFilterLogFormatter.m │ │ │ ├── DDDispatchQueueLogFormatter.h │ │ │ ├── DDDispatchQueueLogFormatter.m │ │ │ ├── DDMultiFormatter.h │ │ │ ├── DDMultiFormatter.m │ │ │ └── README.txt │ └── ffmpeg │ │ └── .gitignore │ ├── Info.plist │ ├── MainViewController.h │ ├── MainViewController.m │ ├── Resources │ └── web │ │ ├── index.css │ │ ├── index.html │ │ ├── index.js │ │ ├── js_disabled.css │ │ └── js_enabled.css │ ├── ViewController.h │ ├── ViewController.m │ ├── Web │ ├── FileManagementViewController.h │ ├── FileManagementViewController.m │ ├── HTTPUploader.h │ ├── HTTPUploader.m │ ├── WebUtils.h │ └── WebUtils.m │ └── main.m ├── How_to_build_ffmpeg_with_openssl.md ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | *.DS_Store 5 | 6 | ## Build generated 7 | build/ 8 | DerivedData/ 9 | 10 | ## Various settings 11 | *.pbxuser 12 | !default.pbxuser 13 | *.mode1v3 14 | !default.mode1v3 15 | *.mode2v3 16 | !default.mode2v3 17 | *.perspectivev3 18 | !default.perspectivev3 19 | xcuserdata/ 20 | 21 | ## Other 22 | *.moved-aside 23 | *.xcuserstate 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 52 | 53 | fastlane/report.xml 54 | fastlane/screenshots 55 | 56 | #Code Injection 57 | # 58 | # After new code Injection tools there's a generated folder /iOSInjectionProject 59 | # https://github.com/johnno1962/injectionforxcode 60 | 61 | iOSInjectionProject/ 62 | -------------------------------------------------------------------------------- /DLGPlayer/DLGPlayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayer.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 09/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DLGPlayerDef.h" 11 | 12 | typedef void (^onPauseComplete)(void); 13 | 14 | @interface DLGPlayer : NSObject 15 | 16 | @property (readonly, strong) UIView *playerView; 17 | 18 | @property (nonatomic) double minBufferDuration; 19 | @property (nonatomic) double maxBufferDuration; 20 | @property (nonatomic) double position; 21 | @property (nonatomic) double duration; 22 | @property (nonatomic) BOOL opened; 23 | @property (nonatomic) BOOL playing; 24 | @property (nonatomic) BOOL buffering; 25 | @property (nonatomic, strong) NSDictionary *metadata; 26 | 27 | - (void)open:(NSString *)url; 28 | - (void)close; 29 | - (void)play; 30 | - (void)pause; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /DLGPlayer/DLGPlayerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerViewController.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 06/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DLGPlayer.h" 11 | 12 | typedef enum : NSUInteger { 13 | DLGPlayerStatusNone, 14 | DLGPlayerStatusOpening, 15 | DLGPlayerStatusOpened, 16 | DLGPlayerStatusPlaying, 17 | DLGPlayerStatusBuffering, 18 | DLGPlayerStatusPaused, 19 | DLGPlayerStatusEOF, 20 | DLGPlayerStatusClosing, 21 | DLGPlayerStatusClosed, 22 | } DLGPlayerStatus; 23 | 24 | @interface DLGPlayerViewController : UIViewController 25 | 26 | @property (nonatomic, copy) NSString *url; 27 | @property (nonatomic) BOOL autoplay; 28 | @property (nonatomic) BOOL repeat; 29 | @property (nonatomic) BOOL preventFromScreenLock; 30 | @property (nonatomic) BOOL restorePlayAfterAppEnterForeground; 31 | @property (nonatomic, readonly) DLGPlayerStatus status; 32 | 33 | - (void)open; 34 | - (void)close; 35 | - (void)play; 36 | - (void)pause; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /DLGPlayer/codec/DLGPlayerAudioManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerAudioManager.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 08/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void(^DLGPlayerAudioManagerFrameReaderBlock)(float *data, UInt32 num, UInt32 channels); 12 | 13 | @interface DLGPlayerAudioManager : NSObject 14 | 15 | @property (nonatomic, copy) DLGPlayerAudioManagerFrameReaderBlock frameReaderBlock; 16 | @property (nonatomic) float volume; 17 | 18 | - (BOOL)open:(NSError **)error; 19 | - (BOOL)play; 20 | - (BOOL)play:(NSError **)error; 21 | - (BOOL)pause; 22 | - (BOOL)pause:(NSError **)error; 23 | - (BOOL)close; 24 | - (BOOL)close:(NSArray **)errors; 25 | 26 | - (double)sampleRate; 27 | - (UInt32)channels; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /DLGPlayer/codec/DLGPlayerDecoder.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerDecoder.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 05/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DLGPlayerDecoder : NSObject 12 | 13 | @property (nonatomic) BOOL isYUV; 14 | @property (nonatomic) BOOL hasVideo; 15 | @property (nonatomic) BOOL hasAudio; 16 | @property (nonatomic) BOOL hasPicture; 17 | @property (nonatomic) BOOL isEOF; 18 | 19 | @property (nonatomic) double rotation; 20 | @property (nonatomic) double duration; 21 | @property (nonatomic, strong) NSDictionary *metadata; 22 | 23 | @property (nonatomic) UInt32 audioChannels; 24 | @property (nonatomic) float audioSampleRate; 25 | 26 | @property (nonatomic) double videoFPS; 27 | @property (nonatomic) double videoTimebase; 28 | @property (nonatomic) double audioTimebase; 29 | 30 | - (BOOL)open:(NSString *)url error:(NSError **)error; 31 | - (void)close; 32 | - (void)prepareClose; 33 | - (NSArray *)readFrames; 34 | - (void)seek:(double)position; 35 | - (int)videoWidth; 36 | - (int)videoHeight; 37 | - (BOOL)isYUV; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /DLGPlayer/common/DLGPlayerDef.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerDef.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 05/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #ifndef DLGPlayerDef_h 10 | #define DLGPlayerDef_h 11 | 12 | #define DLGPlayerLocalizedStringTable @"DLGPlayerStrings" 13 | 14 | #define DLGPlayerMinBufferDuration 2 15 | #define DLGPlayerMaxBufferDuration 5 16 | 17 | #define DLGPlayerErrorDomainDecoder @"DLGPlayerDecoder" 18 | #define DLGPlayerErrorDomainAudioManager @"DLGPlayerAudioManager" 19 | 20 | #define DLGPlayerErrorCodeInvalidURL -1 21 | #define DLGPlayerErrorCodeCannotOpenInput -2 22 | #define DLGPlayerErrorCodeCannotFindStreamInfo -3 23 | #define DLGPlayerErrorCodeNoVideoAndAudioStream -4 24 | 25 | #define DLGPlayerErrorCodeNoAudioOuput -5 26 | #define DLGPlayerErrorCodeNoAudioChannel -6 27 | #define DLGPlayerErrorCodeNoAudioSampleRate -7 28 | #define DLGPlayerErrorCodeNoAudioVolume -8 29 | #define DLGPlayerErrorCodeCannotSetAudioCategory -9 30 | #define DLGPlayerErrorCodeCannotSetAudioActive -10 31 | #define DLGPlayerErrorCodeCannotInitAudioUnit -11 32 | #define DLGPlayerErrorCodeCannotCreateAudioComponent -12 33 | #define DLGPlayerErrorCodeCannotGetAudioStreamDescription -13 34 | #define DLGPlayerErrorCodeCannotSetAudioRenderCallback -14 35 | #define DLGPlayerErrorCodeCannotUninitAudioUnit -15 36 | #define DLGPlayerErrorCodeCannotDisposeAudioUnit -16 37 | #define DLGPlayerErrorCodeCannotDeactivateAudio -17 38 | #define DLGPlayerErrorCodeCannotStartAudioUnit -18 39 | #define DLGPlayerErrorCodeCannotStopAudioUnit -19 40 | 41 | #pragma mark - Notification 42 | #define DLGPlayerNotificationOpened @"DLGPlayerNotificationOpened" 43 | #define DLGPlayerNotificationClosed @"DLGPlayerNotificationClosed" 44 | #define DLGPlayerNotificationEOF @"DLGPlayerNotificationEOF" 45 | #define DLGPlayerNotificationBufferStateChanged @"DLGPlayerNotificationBufferStateChanged" 46 | #define DLGPlayerNotificationError @"DLGPlayerNotificationError" 47 | 48 | #pragma mark - Notification Key 49 | #define DLGPlayerNotificationBufferStateKey @"DLGPlayerNotificationBufferStateKey" 50 | #define DLGPlayerNotificationSeekStateKey @"DLGPlayerNotificationSeekStateKey" 51 | #define DLGPlayerNotificationErrorKey @"DLGPlayerNotificationErrorKey" 52 | #define DLGPlayerNotificationRawErrorKey @"DLGPlayerNotificationRawErrorKey" 53 | 54 | #endif /* DLGPlayerDef_h */ 55 | -------------------------------------------------------------------------------- /DLGPlayer/common/DLGPlayerUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerUtils.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 05/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DLGPlayerUtils : NSObject 12 | 13 | + (BOOL)createError:(NSError **)error withDomain:(NSString *)domain andCode:(NSInteger)code andMessage:(NSString *)message; 14 | + (BOOL)createError:(NSError **)error withDomain:(NSString *)domain andCode:(NSInteger)code andMessage:(NSString *)message andRawError:(NSError *)rawError; 15 | + (NSString *)localizedString:(NSString *)name; 16 | + (NSString *)durationStringFromSeconds:(int)seconds; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /DLGPlayer/common/DLGPlayerUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerUtils.m 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 05/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "DLGPlayerUtils.h" 10 | #import "DLGPlayerDef.h" 11 | 12 | @implementation DLGPlayerUtils 13 | 14 | + (BOOL)createError:(NSError **)error withDomain:(NSString *)domain andCode:(NSInteger)code andMessage:(NSString *)message { 15 | if (error == nil) return NO; 16 | NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; 17 | if (message != nil) userInfo[NSLocalizedDescriptionKey] = message; 18 | *error = [NSError errorWithDomain:domain 19 | code:code 20 | userInfo:userInfo]; 21 | return YES; 22 | } 23 | 24 | + (BOOL)createError:(NSError **)error withDomain:(NSString *)domain andCode:(NSInteger)code andMessage:(NSString *)message andRawError:(NSError *)rawError { 25 | if (error == nil) return NO; 26 | NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; 27 | if (message != nil) userInfo[NSLocalizedDescriptionKey] = message; 28 | if (rawError != nil) userInfo[NSLocalizedFailureReasonErrorKey] = rawError; 29 | *error = [NSError errorWithDomain:domain 30 | code:code 31 | userInfo:userInfo]; 32 | return YES; 33 | } 34 | 35 | + (NSString *)localizedString:(NSString *)name { 36 | return NSLocalizedStringFromTable(name, DLGPlayerLocalizedStringTable, nil); 37 | } 38 | 39 | + (NSString *)durationStringFromSeconds:(int)seconds { 40 | NSMutableString *ms = [[NSMutableString alloc] initWithCapacity:8]; 41 | if (seconds < 0) { [ms appendString:@"∞"]; return ms; } 42 | 43 | int h = seconds / 3600; 44 | [ms appendFormat:@"%d:", h]; 45 | int m = seconds / 60 % 60; 46 | if (m < 10) [ms appendString:@"0"]; 47 | [ms appendFormat:@"%d:", m]; 48 | int s = seconds % 60; 49 | if (s < 10) [ms appendString:@"0"]; 50 | [ms appendFormat:@"%d", s]; 51 | return ms; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /DLGPlayer/frame/DLGPlayerAudioFrame.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerAudioFrame.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 08/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "DLGPlayerFrame.h" 10 | 11 | @interface DLGPlayerAudioFrame : DLGPlayerFrame 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DLGPlayer/frame/DLGPlayerAudioFrame.m: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerAudioFrame.m 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 08/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "DLGPlayerAudioFrame.h" 10 | 11 | @implementation DLGPlayerAudioFrame 12 | 13 | - (id)init { 14 | self = [super init]; 15 | if (self) { 16 | self.type = kDLGPlayerFrameTypeAudio; 17 | } 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /DLGPlayer/frame/DLGPlayerFrame.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerFrame.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 08/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum : NSUInteger { 12 | kDLGPlayerFrameTypeNone, 13 | kDLGPlayerFrameTypeVideo, 14 | kDLGPlayerFrameTypeAudio 15 | } DLGPlayerFrameType; 16 | 17 | @interface DLGPlayerFrame : NSObject 18 | 19 | @property (nonatomic) DLGPlayerFrameType type; 20 | @property (nonatomic) NSData *data; 21 | @property (nonatomic) double position; 22 | @property (nonatomic) double duration; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /DLGPlayer/frame/DLGPlayerFrame.m: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerFrame.m 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 08/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "DLGPlayerFrame.h" 10 | 11 | @implementation DLGPlayerFrame 12 | 13 | - (id)init { 14 | self = [super init]; 15 | if (self) { 16 | _type = kDLGPlayerFrameTypeNone; 17 | _data = nil; 18 | } 19 | return self; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /DLGPlayer/frame/DLGPlayerVideoFrame.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerVideoFrame.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 05/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "DLGPlayerFrame.h" 10 | #import 11 | 12 | typedef enum : NSUInteger { 13 | kDLGPlayerVideoFrameTypeNone, 14 | kDLGPlayerVideoFrameTypeRGB, 15 | kDLGPlayerVideoFrameTypeYUV 16 | } DLGPlayerVideoFrameType; 17 | 18 | @interface DLGPlayerVideoFrame : DLGPlayerFrame 19 | 20 | @property (nonatomic) DLGPlayerVideoFrameType videoType; 21 | @property (nonatomic) int width; 22 | @property (nonatomic) int height; 23 | 24 | - (BOOL)prepareRender:(GLuint)program; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /DLGPlayer/frame/DLGPlayerVideoFrame.m: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerVideoFrame.m 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 05/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "DLGPlayerVideoFrame.h" 10 | 11 | @implementation DLGPlayerVideoFrame 12 | 13 | - (id)init { 14 | self = [super init]; 15 | if (self) { 16 | self.type = kDLGPlayerFrameTypeVideo; 17 | } 18 | return self; 19 | } 20 | 21 | - (BOOL)prepareRender:(GLuint)program { 22 | return NO; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /DLGPlayer/frame/DLGPlayerVideoRGBFrame.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerVideoRGBFrame.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 09/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "DLGPlayerVideoFrame.h" 10 | 11 | @interface DLGPlayerVideoRGBFrame : DLGPlayerVideoFrame 12 | 13 | @property (nonatomic) NSUInteger linesize; 14 | @property (nonatomic) BOOL hasAlpha; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /DLGPlayer/frame/DLGPlayerVideoRGBFrame.m: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerVideoRGBFrame.m 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 09/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "DLGPlayerVideoRGBFrame.h" 10 | 11 | @interface DLGPlayerVideoRGBFrame () { 12 | GLint _sampler; 13 | GLuint _texture; 14 | GLint _format; 15 | } 16 | 17 | @end 18 | 19 | @implementation DLGPlayerVideoRGBFrame 20 | 21 | - (id)init { 22 | self = [super init]; 23 | if (self) { 24 | self.videoType = kDLGPlayerVideoFrameTypeRGB; 25 | _sampler = -1; 26 | _texture = 0; 27 | _hasAlpha = NO; 28 | _format = GL_RGB; 29 | } 30 | return self; 31 | } 32 | 33 | - (void)dealloc { 34 | [self deleteTexture]; 35 | } 36 | 37 | - (void)deleteTexture { 38 | if (_texture != 0) { 39 | glDeleteTextures(1, &_texture); 40 | _texture = 0; 41 | } 42 | } 43 | 44 | - (BOOL)prepareRender:(GLuint)program { 45 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 46 | 47 | if (_texture == 0) { 48 | glGenTextures(1, &_texture); 49 | if (_texture == 0) return NO; 50 | } 51 | 52 | glBindTexture(GL_TEXTURE_2D, _texture); 53 | glTexImage2D(GL_TEXTURE_2D, 54 | 0, 55 | _format, 56 | self.width, 57 | self.height, 58 | 0, 59 | _format, 60 | GL_UNSIGNED_BYTE, 61 | self.data.bytes); 62 | 63 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 64 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 65 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 66 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 67 | 68 | if (_sampler == -1) { 69 | _sampler = glGetUniformLocation(program, "s_texture"); 70 | if (_sampler == -1) return NO; 71 | } 72 | 73 | glActiveTexture(GL_TEXTURE0); 74 | glBindTexture(GL_TEXTURE_2D, _texture); 75 | glUniform1i(_sampler, 0); 76 | 77 | return YES; 78 | } 79 | 80 | - (void)setHasAlpha:(BOOL)hasAlpha { 81 | _hasAlpha = hasAlpha; 82 | _format = hasAlpha ? GL_RGBA : GL_RGB; 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /DLGPlayer/frame/DLGPlayerVideoYUVFrame.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerVideoYUVFrame.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 09/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "DLGPlayerVideoFrame.h" 10 | 11 | @interface DLGPlayerVideoYUVFrame : DLGPlayerVideoFrame 12 | 13 | @property (nonatomic, strong) NSData *Y; // Luma 14 | @property (nonatomic, strong) NSData *Cb; // Chroma Blue 15 | @property (nonatomic, strong) NSData *Cr; // Chroma Red 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /DLGPlayer/frame/DLGPlayerVideoYUVFrame.m: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerVideoYUVFrame.m 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 09/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "DLGPlayerVideoYUVFrame.h" 10 | 11 | @interface DLGPlayerVideoYUVFrame () { 12 | GLint _sampler[3]; 13 | GLuint _texture[3]; 14 | } 15 | 16 | @end 17 | 18 | @implementation DLGPlayerVideoYUVFrame 19 | 20 | - (id)init { 21 | self = [super init]; 22 | if (self) { 23 | self.videoType = kDLGPlayerVideoFrameTypeYUV; 24 | for (int i = 0; i < 3; ++i) { 25 | _sampler[i] = -1; 26 | _texture[i] = 0; 27 | } 28 | } 29 | return self; 30 | } 31 | 32 | - (void)dealloc { 33 | [self deleteTexture]; 34 | } 35 | 36 | - (void)deleteTexture { 37 | if (_texture[0] != 0) { 38 | glDeleteTextures(3, _texture); 39 | for (int i = 0; i < 3; ++i) _texture[i] = 0; 40 | } 41 | } 42 | 43 | - (BOOL)initSampler:(GLuint)program { 44 | if (_sampler[0] == -1) { 45 | _sampler[0] = glGetUniformLocation(program, "s_texture_y"); 46 | if (_sampler[0] == -1) return NO; 47 | } 48 | if (_sampler[1] == -1) { 49 | _sampler[1] = glGetUniformLocation(program, "s_texture_u"); 50 | if (_sampler[1] == -1) return NO; 51 | } 52 | if (_sampler[2] == -1) { 53 | _sampler[2] = glGetUniformLocation(program, "s_texture_v"); 54 | if (_sampler[2] == -1) return NO; 55 | } 56 | return YES; 57 | } 58 | 59 | - (BOOL)prepareRender:(GLuint)program { 60 | const int w = self.width; 61 | const int h = self.height; 62 | 63 | if (_Y.length != w * h) return NO; 64 | if (_Cb.length != ((w * h) / 4)) return NO; 65 | if (_Cr.length != ((w * h) / 4)) return NO; 66 | 67 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 68 | 69 | if (_texture[0] == 0) { 70 | glGenTextures(3, _texture); 71 | if (_texture[0] == 0) return NO; 72 | } 73 | 74 | const UInt8 *data[3] = { _Y.bytes, _Cb.bytes, _Cr.bytes }; 75 | const int width[3] = { w, w / 2, w / 2 }; 76 | const int height[3] = { h, h / 2, h / 2 }; 77 | 78 | for (int i = 0; i < 3; ++i) { 79 | glBindTexture(GL_TEXTURE_2D, _texture[i]); 80 | glTexImage2D(GL_TEXTURE_2D, 81 | 0, 82 | GL_LUMINANCE, 83 | width[i], 84 | height[i], 85 | 0, 86 | GL_LUMINANCE, 87 | GL_UNSIGNED_BYTE, 88 | data[i]); 89 | 90 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 91 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 92 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 93 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 94 | } 95 | 96 | if (![self initSampler:program]) return NO; 97 | 98 | for (int i = 0; i < 3; ++i) { 99 | glActiveTexture(GL_TEXTURE0 + i); 100 | glBindTexture(GL_TEXTURE_2D, _texture[i]); 101 | glUniform1i(_sampler[i], i); 102 | } 103 | 104 | return YES; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /DLGPlayer/resource/Base.lproj/DLGPlayerStrings.strings: -------------------------------------------------------------------------------- 1 | /* 2 | DLGPlayerStrings.strings 3 | DLGPlayer 4 | 5 | Created by Liu Junqi on 05/12/2016. 6 | Copyright © 2016 Liu Junqi. All rights reserved. 7 | */ 8 | "DLG_PLAYER_STRINGS_INVALID_URL" = "Invalid URL"; 9 | "DLG_PLAYER_STRINGS_CANNOT_OPEN_INPUT" = "Cannot open input"; 10 | "DLG_PLAYER_STRINGS_CANNOT_FIND_STREAM_INFO" = "Cannot find stream info"; 11 | "DLG_PLAYER_STRINGS_NO_VIDEO_AND_AUDIO_STREAM" = "No video and audio streams"; 12 | 13 | "DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT" = "No audio output"; 14 | "DLG_PLAYER_STRINGS_NO_AUDIO_CHANNEL" = "No audio channel"; 15 | "DLG_PLAYER_STRINGS_NO_AUDIO_SAMPLE_RATE" = "No audio sample rate"; 16 | "DLG_PLAYER_STRINGS_NO_AUDIO_VOLUME" = "No audio volume"; 17 | "DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_CATEGORY" = "Cannot set audio category"; 18 | "DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_ACTIVE" = "Cannot set audio active"; 19 | "DLG_PLAYER_STRINGS_CANNOT_INIT_AUDIO_UNIT" = "Cannot initialize audio unit"; 20 | "DLG_PLAYER_STRINGS_CANNOT_CREATE_AUDIO_UNIT" = "Cannot create audio unit"; 21 | "DLG_PLAYER_STRINGS_CANNOT_GET_AUDIO_STREAM_DESCRIPTION" = "Cannot get audio stream description"; 22 | "DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_RENDER_CALLBACK" = "Cannot set audio render callback"; 23 | "DLG_PLAYER_STRINGS_CANNOT_UNINIT_AUDIO_UNIT" = "Cannot uninitialize audio unit"; 24 | "DLG_PLAYER_STRINGS_CANNOT_DISPOSE_AUDIO_UNIT" = "Cannot dispose audio unit"; 25 | "DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO" = "Cannot deactivate audio"; 26 | "DLG_PLAYER_STRINGS_CANNOT_START_AUDIO_UNIT" = "Cannot start audio unit"; 27 | "DLG_PLAYER_STRINGS_CANNOT_STOP_AUDIO_UNIT" = "Cannot stop audio unit"; 28 | -------------------------------------------------------------------------------- /DLGPlayer/resource/DLGPlayerRGBFragmentShader.glsl: -------------------------------------------------------------------------------- 1 | varying highp vec2 v_texcoord; 2 | uniform sampler2D s_texture; 3 | 4 | void main() { 5 | gl_FragColor = texture2D(s_texture, v_texcoord); 6 | } 7 | -------------------------------------------------------------------------------- /DLGPlayer/resource/DLGPlayerRotationScaleVertexShader.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 position; 2 | attribute vec2 texcoord; 3 | uniform mat4 projection; 4 | uniform mat3 rotation; 5 | uniform mat3 ratio; 6 | uniform mat3 scale; 7 | uniform mat3 viewratio; 8 | varying vec2 v_texcoord; 9 | 10 | void main() { 11 | gl_Position = projection * vec4(scale * viewratio * rotation * ratio * position.xyz, 1.0); 12 | v_texcoord = texcoord; 13 | } 14 | -------------------------------------------------------------------------------- /DLGPlayer/resource/DLGPlayerRotationVertexShader.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 position; 2 | attribute vec2 texcoord; 3 | uniform mat4 projection; 4 | uniform mat3 rotation; 5 | varying vec2 v_texcoord; 6 | 7 | void main() { 8 | gl_Position = projection * vec4(rotation * position.xyz, 1.0); 9 | v_texcoord = texcoord; 10 | } 11 | -------------------------------------------------------------------------------- /DLGPlayer/resource/DLGPlayerVertexShader.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 position; 2 | attribute vec2 texcoord; 3 | uniform mat4 projection; 4 | varying vec2 v_texcoord; 5 | 6 | void main() { 7 | gl_Position = projection * position; 8 | v_texcoord = texcoord; 9 | } 10 | -------------------------------------------------------------------------------- /DLGPlayer/resource/DLGPlayerYUVFragmentShader.glsl: -------------------------------------------------------------------------------- 1 | varying highp vec2 v_texcoord; 2 | uniform sampler2D s_texture_y; 3 | uniform sampler2D s_texture_u; 4 | uniform sampler2D s_texture_v; 5 | 6 | void main() { 7 | highp float y = texture2D(s_texture_y, v_texcoord).r; 8 | highp float u = texture2D(s_texture_u, v_texcoord).r - 0.5; 9 | highp float v = texture2D(s_texture_v, v_texcoord).r - 0.5; 10 | 11 | highp float r = y + 1.402 * v; 12 | highp float g = y - 0.344 * u - 0.714 * v; 13 | highp float b = y + 1.772 * u; 14 | 15 | gl_FragColor = vec4(r, g, b, 1); 16 | } 17 | -------------------------------------------------------------------------------- /DLGPlayer/resource/en.lproj/DLGPlayerStrings.strings: -------------------------------------------------------------------------------- 1 | /* 2 | DLGPlayerStrings.strings 3 | DLGPlayer 4 | 5 | Created by Liu Junqi on 05/12/2016. 6 | Copyright © 2016 Liu Junqi. All rights reserved. 7 | */ 8 | "DLG_PLAYER_STRINGS_INVALID_URL" = "Invalid URL"; 9 | "DLG_PLAYER_STRINGS_CANNOT_OPEN_INPUT" = "Cannot open input"; 10 | "DLG_PLAYER_STRINGS_CANNOT_FIND_STREAM_INFO" = "Cannot find stream info"; 11 | "DLG_PLAYER_STRINGS_NO_VIDEO_AND_AUDIO_STREAM" = "No video and audio streams"; 12 | 13 | "DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT" = "No audio output"; 14 | "DLG_PLAYER_STRINGS_NO_AUDIO_CHANNEL" = "No audio channel"; 15 | "DLG_PLAYER_STRINGS_NO_AUDIO_SAMPLE_RATE" = "No audio sample rate"; 16 | "DLG_PLAYER_STRINGS_NO_AUDIO_VOLUME" = "No audio volume"; 17 | "DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_CATEGORY" = "Cannot set audio category"; 18 | "DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_ACTIVE" = "Cannot set audio active"; 19 | "DLG_PLAYER_STRINGS_CANNOT_INIT_AUDIO_UNIT" = "Cannot initialize audio unit"; 20 | "DLG_PLAYER_STRINGS_CANNOT_CREATE_AUDIO_UNIT" = "Cannot create audio unit"; 21 | "DLG_PLAYER_STRINGS_CANNOT_GET_AUDIO_STREAM_DESCRIPTION" = "Cannot get audio stream description"; 22 | "DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_RENDER_CALLBACK" = "Cannot set audio render callback"; 23 | "DLG_PLAYER_STRINGS_CANNOT_UNINIT_AUDIO_UNIT" = "Cannot uninitialize audio unit"; 24 | "DLG_PLAYER_STRINGS_CANNOT_DISPOSE_AUDIO_UNIT" = "Cannot dispose audio unit"; 25 | "DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO" = "Cannot deactivate audio"; 26 | "DLG_PLAYER_STRINGS_CANNOT_START_AUDIO_UNIT" = "Cannot start audio unit"; 27 | "DLG_PLAYER_STRINGS_CANNOT_STOP_AUDIO_UNIT" = "Cannot stop audio unit"; 28 | -------------------------------------------------------------------------------- /DLGPlayer/resource/zh-Hans.lproj/DLGPlayerStrings.strings: -------------------------------------------------------------------------------- 1 | /* 2 | DLGPlayerStrings.strings 3 | DLGPlayer 4 | 5 | Created by Liu Junqi on 05/12/2016. 6 | Copyright © 2016 Liu Junqi. All rights reserved. 7 | */ 8 | "DLG_PLAYER_STRINGS_INVALID_URL" = "无效的URL"; 9 | "DLG_PLAYER_STRINGS_CANNOT_OPEN_INPUT" = "无法打开输入源"; 10 | "DLG_PLAYER_STRINGS_CANNOT_FIND_STREAM_INFO" = "无法获取流信息"; 11 | "DLG_PLAYER_STRINGS_NO_VIDEO_AND_AUDIO_STREAM" = "无视频流和音频流"; 12 | 13 | "DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT" = "无音频输出"; 14 | "DLG_PLAYER_STRINGS_NO_AUDIO_CHANNEL" = "无音频声道"; 15 | "DLG_PLAYER_STRINGS_NO_AUDIO_SAMPLE_RATE" = "无音频采样率"; 16 | "DLG_PLAYER_STRINGS_NO_AUDIO_VOLUME" = "无音频音量"; 17 | "DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_CATEGORY" = "无法设置音频种类"; 18 | "DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_ACTIVE" = "无法激活音频"; 19 | "DLG_PLAYER_STRINGS_CANNOT_INIT_AUDIO_UNIT" = "无法初始化音频单元"; 20 | "DLG_PLAYER_STRINGS_CANNOT_CREATE_AUDIO_UNIT" = "无法创建音频单元"; 21 | "DLG_PLAYER_STRINGS_CANNOT_GET_AUDIO_STREAM_DESCRIPTION" = "无法获取音频流信息"; 22 | "DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_RENDER_CALLBACK" = "无法设置音频渲染回调"; 23 | "DLG_PLAYER_STRINGS_CANNOT_UNINIT_AUDIO_UNIT" = "无法清空音频单元"; 24 | "DLG_PLAYER_STRINGS_CANNOT_DISPOSE_AUDIO_UNIT" = "无法释放音频单元"; 25 | "DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO" = "无法关闭音频"; 26 | "DLG_PLAYER_STRINGS_CANNOT_START_AUDIO_UNIT" = "无法启动音频单元"; 27 | "DLG_PLAYER_STRINGS_CANNOT_STOP_AUDIO_UNIT" = "无法停止音频单元"; 28 | 29 | -------------------------------------------------------------------------------- /DLGPlayer/view/DLGPlayerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DLGPlayerView.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 05/12/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class DLGPlayerVideoFrame; 12 | 13 | @interface DLGPlayerView : UIView 14 | 15 | @property (nonatomic) CGSize contentSize; 16 | @property (nonatomic) CGFloat rotation; 17 | @property (nonatomic) BOOL isYUV; 18 | @property (nonatomic) BOOL keepLastFrame; 19 | 20 | - (void)render:(DLGPlayerVideoFrame *)frame; 21 | - (void)clear; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Example/DLGPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/DLGPlayer.xcodeproj/project.xcworkspace/xcshareddata/DLGPlayer.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "c0d11c02-cea6-2241-a6fc-c7daa13e666c", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | "c0d11c02-cea6-2241-a6fc-c7daa13e666c" : { 5 | "DVTSourceControlWorkingCopyRepositoryBranchesLocationKey" : "branches", 6 | "DVTSourceControlWorkingCopyRepositoryTagsLocationKey" : "tags", 7 | "DVTSourceControlWorkingCopyRepositoryPrimaryBranchLocationKey" : "trunk" 8 | } 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 11 | "c0d11c02-cea6-2241-a6fc-c7daa13e666c" : 9223372036854775807 12 | }, 13 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "573A64D1-919F-4B27-A097-FA9C03D01C79", 14 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 15 | "c0d11c02-cea6-2241-a6fc-c7daa13e666c" : "pinkart\/" 16 | }, 17 | "DVTSourceControlWorkspaceBlueprintNameKey" : "DLGPlayer", 18 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 19 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "trunk\/04_Personal\/liujunqi\/DLGPlayer\/DLGPlayer.xcodeproj", 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 21 | { 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/106.14.45.0\/svn\/PinkArt", 23 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Subversion", 24 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "c0d11c02-cea6-2241-a6fc-c7daa13e666c" 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /Example/DLGPlayer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 29/11/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Example/DLGPlayer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 29/11/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /Example/DLGPlayer/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Categories/DDData.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface NSData (DDData) 4 | 5 | - (NSData *)md5Digest; 6 | 7 | - (NSData *)sha1Digest; 8 | 9 | - (NSString *)hexStringValue; 10 | 11 | - (NSString *)base64Encoded; 12 | - (NSData *)base64Decoded; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Categories/DDData.m: -------------------------------------------------------------------------------- 1 | #import "DDData.h" 2 | #import 3 | 4 | 5 | @implementation NSData (DDData) 6 | 7 | static char encodingTable[64] = { 8 | 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 9 | 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 10 | 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 11 | 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' }; 12 | 13 | - (NSData *)md5Digest 14 | { 15 | unsigned char result[CC_MD5_DIGEST_LENGTH]; 16 | 17 | CC_MD5([self bytes], (CC_LONG)[self length], result); 18 | return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH]; 19 | } 20 | 21 | - (NSData *)sha1Digest 22 | { 23 | unsigned char result[CC_SHA1_DIGEST_LENGTH]; 24 | 25 | CC_SHA1([self bytes], (CC_LONG)[self length], result); 26 | return [NSData dataWithBytes:result length:CC_SHA1_DIGEST_LENGTH]; 27 | } 28 | 29 | - (NSString *)hexStringValue 30 | { 31 | NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:([self length] * 2)]; 32 | 33 | const unsigned char *dataBuffer = [self bytes]; 34 | int i; 35 | 36 | for (i = 0; i < [self length]; ++i) 37 | { 38 | [stringBuffer appendFormat:@"%02x", (unsigned int)dataBuffer[i]]; 39 | } 40 | 41 | return [stringBuffer copy]; 42 | } 43 | 44 | - (NSString *)base64Encoded 45 | { 46 | const unsigned char *bytes = [self bytes]; 47 | NSMutableString *result = [NSMutableString stringWithCapacity:[self length]]; 48 | unsigned long ixtext = 0; 49 | unsigned long lentext = [self length]; 50 | long ctremaining = 0; 51 | unsigned char inbuf[3], outbuf[4]; 52 | unsigned short i = 0; 53 | unsigned short charsonline = 0, ctcopy = 0; 54 | unsigned long ix = 0; 55 | 56 | while( YES ) 57 | { 58 | ctremaining = lentext - ixtext; 59 | if( ctremaining <= 0 ) break; 60 | 61 | for( i = 0; i < 3; i++ ) { 62 | ix = ixtext + i; 63 | if( ix < lentext ) inbuf[i] = bytes[ix]; 64 | else inbuf [i] = 0; 65 | } 66 | 67 | outbuf [0] = (inbuf [0] & 0xFC) >> 2; 68 | outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4); 69 | outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6); 70 | outbuf [3] = inbuf [2] & 0x3F; 71 | ctcopy = 4; 72 | 73 | switch( ctremaining ) 74 | { 75 | case 1: 76 | ctcopy = 2; 77 | break; 78 | case 2: 79 | ctcopy = 3; 80 | break; 81 | } 82 | 83 | for( i = 0; i < ctcopy; i++ ) 84 | [result appendFormat:@"%c", encodingTable[outbuf[i]]]; 85 | 86 | for( i = ctcopy; i < 4; i++ ) 87 | [result appendString:@"="]; 88 | 89 | ixtext += 3; 90 | charsonline += 4; 91 | } 92 | 93 | return [NSString stringWithString:result]; 94 | } 95 | 96 | - (NSData *)base64Decoded 97 | { 98 | const unsigned char *bytes = [self bytes]; 99 | NSMutableData *result = [NSMutableData dataWithCapacity:[self length]]; 100 | 101 | unsigned long ixtext = 0; 102 | unsigned long lentext = [self length]; 103 | unsigned char ch = 0; 104 | unsigned char inbuf[4] = {0, 0, 0, 0}; 105 | unsigned char outbuf[3] = {0, 0, 0}; 106 | short i = 0, ixinbuf = 0; 107 | BOOL flignore = NO; 108 | BOOL flendtext = NO; 109 | 110 | while( YES ) 111 | { 112 | if( ixtext >= lentext ) break; 113 | ch = bytes[ixtext++]; 114 | flignore = NO; 115 | 116 | if( ( ch >= 'A' ) && ( ch <= 'Z' ) ) ch = ch - 'A'; 117 | else if( ( ch >= 'a' ) && ( ch <= 'z' ) ) ch = ch - 'a' + 26; 118 | else if( ( ch >= '0' ) && ( ch <= '9' ) ) ch = ch - '0' + 52; 119 | else if( ch == '+' ) ch = 62; 120 | else if( ch == '=' ) flendtext = YES; 121 | else if( ch == '/' ) ch = 63; 122 | else flignore = YES; 123 | 124 | if( ! flignore ) 125 | { 126 | short ctcharsinbuf = 3; 127 | BOOL flbreak = NO; 128 | 129 | if( flendtext ) 130 | { 131 | if( ! ixinbuf ) break; 132 | if( ( ixinbuf == 1 ) || ( ixinbuf == 2 ) ) ctcharsinbuf = 1; 133 | else ctcharsinbuf = 2; 134 | ixinbuf = 3; 135 | flbreak = YES; 136 | } 137 | 138 | inbuf [ixinbuf++] = ch; 139 | 140 | if( ixinbuf == 4 ) 141 | { 142 | ixinbuf = 0; 143 | outbuf [0] = ( inbuf[0] << 2 ) | ( ( inbuf[1] & 0x30) >> 4 ); 144 | outbuf [1] = ( ( inbuf[1] & 0x0F ) << 4 ) | ( ( inbuf[2] & 0x3C ) >> 2 ); 145 | outbuf [2] = ( ( inbuf[2] & 0x03 ) << 6 ) | ( inbuf[3] & 0x3F ); 146 | 147 | for( i = 0; i < ctcharsinbuf; i++ ) 148 | [result appendBytes:&outbuf[i] length:1]; 149 | } 150 | 151 | if( flbreak ) break; 152 | } 153 | } 154 | 155 | return [NSData dataWithData:result]; 156 | } 157 | 158 | @end 159 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Categories/DDNumber.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface NSNumber (DDNumber) 5 | 6 | + (BOOL)parseString:(NSString *)str intoSInt64:(SInt64 *)pNum; 7 | + (BOOL)parseString:(NSString *)str intoUInt64:(UInt64 *)pNum; 8 | 9 | + (BOOL)parseString:(NSString *)str intoNSInteger:(NSInteger *)pNum; 10 | + (BOOL)parseString:(NSString *)str intoNSUInteger:(NSUInteger *)pNum; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Categories/DDNumber.m: -------------------------------------------------------------------------------- 1 | #import "DDNumber.h" 2 | 3 | 4 | @implementation NSNumber (DDNumber) 5 | 6 | + (BOOL)parseString:(NSString *)str intoSInt64:(SInt64 *)pNum 7 | { 8 | if(str == nil) 9 | { 10 | *pNum = 0; 11 | return NO; 12 | } 13 | 14 | errno = 0; 15 | 16 | // On both 32-bit and 64-bit machines, long long = 64 bit 17 | 18 | *pNum = strtoll([str UTF8String], NULL, 10); 19 | 20 | if(errno != 0) 21 | return NO; 22 | else 23 | return YES; 24 | } 25 | 26 | + (BOOL)parseString:(NSString *)str intoUInt64:(UInt64 *)pNum 27 | { 28 | if(str == nil) 29 | { 30 | *pNum = 0; 31 | return NO; 32 | } 33 | 34 | errno = 0; 35 | 36 | // On both 32-bit and 64-bit machines, unsigned long long = 64 bit 37 | 38 | *pNum = strtoull([str UTF8String], NULL, 10); 39 | 40 | if(errno != 0) 41 | return NO; 42 | else 43 | return YES; 44 | } 45 | 46 | + (BOOL)parseString:(NSString *)str intoNSInteger:(NSInteger *)pNum 47 | { 48 | if(str == nil) 49 | { 50 | *pNum = 0; 51 | return NO; 52 | } 53 | 54 | errno = 0; 55 | 56 | // On LP64, NSInteger = long = 64 bit 57 | // Otherwise, NSInteger = int = long = 32 bit 58 | 59 | *pNum = strtol([str UTF8String], NULL, 10); 60 | 61 | if(errno != 0) 62 | return NO; 63 | else 64 | return YES; 65 | } 66 | 67 | + (BOOL)parseString:(NSString *)str intoNSUInteger:(NSUInteger *)pNum 68 | { 69 | if(str == nil) 70 | { 71 | *pNum = 0; 72 | return NO; 73 | } 74 | 75 | errno = 0; 76 | 77 | // On LP64, NSUInteger = unsigned long = 64 bit 78 | // Otherwise, NSUInteger = unsigned int = unsigned long = 32 bit 79 | 80 | *pNum = strtoul([str UTF8String], NULL, 10); 81 | 82 | if(errno != 0) 83 | return NO; 84 | else 85 | return YES; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Categories/DDRange.h: -------------------------------------------------------------------------------- 1 | /** 2 | * DDRange is the functional equivalent of a 64 bit NSRange. 3 | * The HTTP Server is designed to support very large files. 4 | * On 32 bit architectures (ppc, i386) NSRange uses unsigned 32 bit integers. 5 | * This only supports a range of up to 4 gigabytes. 6 | * By defining our own variant, we can support a range up to 16 exabytes. 7 | * 8 | * All effort is given such that DDRange functions EXACTLY the same as NSRange. 9 | **/ 10 | 11 | #import 12 | #import 13 | 14 | @class NSString; 15 | 16 | typedef struct _DDRange { 17 | UInt64 location; 18 | UInt64 length; 19 | } DDRange; 20 | 21 | typedef DDRange *DDRangePointer; 22 | 23 | NS_INLINE DDRange DDMakeRange(UInt64 loc, UInt64 len) { 24 | DDRange r; 25 | r.location = loc; 26 | r.length = len; 27 | return r; 28 | } 29 | 30 | NS_INLINE UInt64 DDMaxRange(DDRange range) { 31 | return (range.location + range.length); 32 | } 33 | 34 | NS_INLINE BOOL DDLocationInRange(UInt64 loc, DDRange range) { 35 | return (loc - range.location < range.length); 36 | } 37 | 38 | NS_INLINE BOOL DDEqualRanges(DDRange range1, DDRange range2) { 39 | return ((range1.location == range2.location) && (range1.length == range2.length)); 40 | } 41 | 42 | FOUNDATION_EXPORT DDRange DDUnionRange(DDRange range1, DDRange range2); 43 | FOUNDATION_EXPORT DDRange DDIntersectionRange(DDRange range1, DDRange range2); 44 | FOUNDATION_EXPORT NSString *DDStringFromRange(DDRange range); 45 | FOUNDATION_EXPORT DDRange DDRangeFromString(NSString *aString); 46 | 47 | NSInteger DDRangeCompare(DDRangePointer pDDRange1, DDRangePointer pDDRange2); 48 | 49 | @interface NSValue (NSValueDDRangeExtensions) 50 | 51 | + (NSValue *)valueWithDDRange:(DDRange)range; 52 | - (DDRange)ddrangeValue; 53 | 54 | - (NSInteger)ddrangeCompare:(NSValue *)ddrangeValue; 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Categories/DDRange.m: -------------------------------------------------------------------------------- 1 | #import "DDRange.h" 2 | #import "DDNumber.h" 3 | 4 | DDRange DDUnionRange(DDRange range1, DDRange range2) 5 | { 6 | DDRange result; 7 | 8 | result.location = MIN(range1.location, range2.location); 9 | result.length = MAX(DDMaxRange(range1), DDMaxRange(range2)) - result.location; 10 | 11 | return result; 12 | } 13 | 14 | DDRange DDIntersectionRange(DDRange range1, DDRange range2) 15 | { 16 | DDRange result; 17 | 18 | if((DDMaxRange(range1) < range2.location) || (DDMaxRange(range2) < range1.location)) 19 | { 20 | return DDMakeRange(0, 0); 21 | } 22 | 23 | result.location = MAX(range1.location, range2.location); 24 | result.length = MIN(DDMaxRange(range1), DDMaxRange(range2)) - result.location; 25 | 26 | return result; 27 | } 28 | 29 | NSString *DDStringFromRange(DDRange range) 30 | { 31 | return [NSString stringWithFormat:@"{%qu, %qu}", range.location, range.length]; 32 | } 33 | 34 | DDRange DDRangeFromString(NSString *aString) 35 | { 36 | DDRange result = DDMakeRange(0, 0); 37 | 38 | // NSRange will ignore '-' characters, but not '+' characters 39 | NSCharacterSet *cset = [NSCharacterSet characterSetWithCharactersInString:@"+0123456789"]; 40 | 41 | NSScanner *scanner = [NSScanner scannerWithString:aString]; 42 | [scanner setCharactersToBeSkipped:[cset invertedSet]]; 43 | 44 | NSString *str1 = nil; 45 | NSString *str2 = nil; 46 | 47 | BOOL found1 = [scanner scanCharactersFromSet:cset intoString:&str1]; 48 | BOOL found2 = [scanner scanCharactersFromSet:cset intoString:&str2]; 49 | 50 | if(found1) [NSNumber parseString:str1 intoUInt64:&result.location]; 51 | if(found2) [NSNumber parseString:str2 intoUInt64:&result.length]; 52 | 53 | return result; 54 | } 55 | 56 | NSInteger DDRangeCompare(DDRangePointer pDDRange1, DDRangePointer pDDRange2) 57 | { 58 | // Comparison basis: 59 | // Which range would you encouter first if you started at zero, and began walking towards infinity. 60 | // If you encouter both ranges at the same time, which range would end first. 61 | 62 | if(pDDRange1->location < pDDRange2->location) 63 | { 64 | return NSOrderedAscending; 65 | } 66 | if(pDDRange1->location > pDDRange2->location) 67 | { 68 | return NSOrderedDescending; 69 | } 70 | if(pDDRange1->length < pDDRange2->length) 71 | { 72 | return NSOrderedAscending; 73 | } 74 | if(pDDRange1->length > pDDRange2->length) 75 | { 76 | return NSOrderedDescending; 77 | } 78 | 79 | return NSOrderedSame; 80 | } 81 | 82 | @implementation NSValue (NSValueDDRangeExtensions) 83 | 84 | + (NSValue *)valueWithDDRange:(DDRange)range 85 | { 86 | return [NSValue valueWithBytes:&range objCType:@encode(DDRange)]; 87 | } 88 | 89 | - (DDRange)ddrangeValue 90 | { 91 | DDRange result; 92 | [self getValue:&result]; 93 | return result; 94 | } 95 | 96 | - (NSInteger)ddrangeCompare:(NSValue *)other 97 | { 98 | DDRange r1 = [self ddrangeValue]; 99 | DDRange r2 = [other ddrangeValue]; 100 | 101 | return DDRangeCompare(&r1, &r2); 102 | } 103 | 104 | @end 105 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/HTTPAuthenticationRequest.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #if TARGET_OS_IPHONE 4 | // Note: You may need to add the CFNetwork Framework to your project 5 | #import 6 | #endif 7 | 8 | @class HTTPMessage; 9 | 10 | 11 | @interface HTTPAuthenticationRequest : NSObject 12 | { 13 | BOOL isBasic; 14 | BOOL isDigest; 15 | 16 | NSString *base64Credentials; 17 | 18 | NSString *username; 19 | NSString *realm; 20 | NSString *nonce; 21 | NSString *uri; 22 | NSString *qop; 23 | NSString *nc; 24 | NSString *cnonce; 25 | NSString *response; 26 | } 27 | - (id)initWithRequest:(HTTPMessage *)request; 28 | 29 | - (BOOL)isBasic; 30 | - (BOOL)isDigest; 31 | 32 | // Basic 33 | - (NSString *)base64Credentials; 34 | 35 | // Digest 36 | - (NSString *)username; 37 | - (NSString *)realm; 38 | - (NSString *)nonce; 39 | - (NSString *)uri; 40 | - (NSString *)qop; 41 | - (NSString *)nc; 42 | - (NSString *)cnonce; 43 | - (NSString *)response; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/HTTPAuthenticationRequest.m: -------------------------------------------------------------------------------- 1 | #import "HTTPAuthenticationRequest.h" 2 | #import "HTTPMessage.h" 3 | 4 | #if ! __has_feature(objc_arc) 5 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 6 | #endif 7 | 8 | @interface HTTPAuthenticationRequest (PrivateAPI) 9 | - (NSString *)quotedSubHeaderFieldValue:(NSString *)param fromHeaderFieldValue:(NSString *)header; 10 | - (NSString *)nonquotedSubHeaderFieldValue:(NSString *)param fromHeaderFieldValue:(NSString *)header; 11 | @end 12 | 13 | 14 | @implementation HTTPAuthenticationRequest 15 | 16 | - (id)initWithRequest:(HTTPMessage *)request 17 | { 18 | if ((self = [super init])) 19 | { 20 | NSString *authInfo = [request headerField:@"Authorization"]; 21 | 22 | isBasic = NO; 23 | if ([authInfo length] >= 6) 24 | { 25 | isBasic = [[authInfo substringToIndex:6] caseInsensitiveCompare:@"Basic "] == NSOrderedSame; 26 | } 27 | 28 | isDigest = NO; 29 | if ([authInfo length] >= 7) 30 | { 31 | isDigest = [[authInfo substringToIndex:7] caseInsensitiveCompare:@"Digest "] == NSOrderedSame; 32 | } 33 | 34 | if (isBasic) 35 | { 36 | NSMutableString *temp = [[authInfo substringFromIndex:6] mutableCopy]; 37 | CFStringTrimWhitespace((__bridge CFMutableStringRef)temp); 38 | 39 | base64Credentials = [temp copy]; 40 | } 41 | 42 | if (isDigest) 43 | { 44 | username = [self quotedSubHeaderFieldValue:@"username" fromHeaderFieldValue:authInfo]; 45 | realm = [self quotedSubHeaderFieldValue:@"realm" fromHeaderFieldValue:authInfo]; 46 | nonce = [self quotedSubHeaderFieldValue:@"nonce" fromHeaderFieldValue:authInfo]; 47 | uri = [self quotedSubHeaderFieldValue:@"uri" fromHeaderFieldValue:authInfo]; 48 | 49 | // It appears from RFC 2617 that the qop is to be given unquoted 50 | // Tests show that Firefox performs this way, but Safari does not 51 | // Thus we'll attempt to retrieve the value as nonquoted, but we'll verify it doesn't start with a quote 52 | qop = [self nonquotedSubHeaderFieldValue:@"qop" fromHeaderFieldValue:authInfo]; 53 | if(qop && ([qop characterAtIndex:0] == '"')) 54 | { 55 | qop = [self quotedSubHeaderFieldValue:@"qop" fromHeaderFieldValue:authInfo]; 56 | } 57 | 58 | nc = [self nonquotedSubHeaderFieldValue:@"nc" fromHeaderFieldValue:authInfo]; 59 | cnonce = [self quotedSubHeaderFieldValue:@"cnonce" fromHeaderFieldValue:authInfo]; 60 | response = [self quotedSubHeaderFieldValue:@"response" fromHeaderFieldValue:authInfo]; 61 | } 62 | } 63 | return self; 64 | } 65 | 66 | 67 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 68 | #pragma mark Accessors: 69 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 70 | 71 | - (BOOL)isBasic { 72 | return isBasic; 73 | } 74 | 75 | - (BOOL)isDigest { 76 | return isDigest; 77 | } 78 | 79 | - (NSString *)base64Credentials { 80 | return base64Credentials; 81 | } 82 | 83 | - (NSString *)username { 84 | return username; 85 | } 86 | 87 | - (NSString *)realm { 88 | return realm; 89 | } 90 | 91 | - (NSString *)nonce { 92 | return nonce; 93 | } 94 | 95 | - (NSString *)uri { 96 | return uri; 97 | } 98 | 99 | - (NSString *)qop { 100 | return qop; 101 | } 102 | 103 | - (NSString *)nc { 104 | return nc; 105 | } 106 | 107 | - (NSString *)cnonce { 108 | return cnonce; 109 | } 110 | 111 | - (NSString *)response { 112 | return response; 113 | } 114 | 115 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 116 | #pragma mark Private API: 117 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 118 | 119 | /** 120 | * Retrieves a "Sub Header Field Value" from a given header field value. 121 | * The sub header field is expected to be quoted. 122 | * 123 | * In the following header field: 124 | * Authorization: Digest username="Mufasa", qop=auth, response="6629fae4939" 125 | * The sub header field titled 'username' is quoted, and this method would return the value @"Mufasa". 126 | **/ 127 | - (NSString *)quotedSubHeaderFieldValue:(NSString *)param fromHeaderFieldValue:(NSString *)header 128 | { 129 | NSRange startRange = [header rangeOfString:[NSString stringWithFormat:@"%@=\"", param]]; 130 | if(startRange.location == NSNotFound) 131 | { 132 | // The param was not found anywhere in the header 133 | return nil; 134 | } 135 | 136 | NSUInteger postStartRangeLocation = startRange.location + startRange.length; 137 | NSUInteger postStartRangeLength = [header length] - postStartRangeLocation; 138 | NSRange postStartRange = NSMakeRange(postStartRangeLocation, postStartRangeLength); 139 | 140 | NSRange endRange = [header rangeOfString:@"\"" options:0 range:postStartRange]; 141 | if(endRange.location == NSNotFound) 142 | { 143 | // The ending double-quote was not found anywhere in the header 144 | return nil; 145 | } 146 | 147 | NSRange subHeaderRange = NSMakeRange(postStartRangeLocation, endRange.location - postStartRangeLocation); 148 | return [header substringWithRange:subHeaderRange]; 149 | } 150 | 151 | /** 152 | * Retrieves a "Sub Header Field Value" from a given header field value. 153 | * The sub header field is expected to not be quoted. 154 | * 155 | * In the following header field: 156 | * Authorization: Digest username="Mufasa", qop=auth, response="6629fae4939" 157 | * The sub header field titled 'qop' is nonquoted, and this method would return the value @"auth". 158 | **/ 159 | - (NSString *)nonquotedSubHeaderFieldValue:(NSString *)param fromHeaderFieldValue:(NSString *)header 160 | { 161 | NSRange startRange = [header rangeOfString:[NSString stringWithFormat:@"%@=", param]]; 162 | if(startRange.location == NSNotFound) 163 | { 164 | // The param was not found anywhere in the header 165 | return nil; 166 | } 167 | 168 | NSUInteger postStartRangeLocation = startRange.location + startRange.length; 169 | NSUInteger postStartRangeLength = [header length] - postStartRangeLocation; 170 | NSRange postStartRange = NSMakeRange(postStartRangeLocation, postStartRangeLength); 171 | 172 | NSRange endRange = [header rangeOfString:@"," options:0 range:postStartRange]; 173 | if(endRange.location == NSNotFound) 174 | { 175 | // The ending comma was not found anywhere in the header 176 | // However, if the nonquoted param is at the end of the string, there would be no comma 177 | // This is only possible if there are no spaces anywhere 178 | NSRange endRange2 = [header rangeOfString:@" " options:0 range:postStartRange]; 179 | if(endRange2.location != NSNotFound) 180 | { 181 | return nil; 182 | } 183 | else 184 | { 185 | return [header substringWithRange:postStartRange]; 186 | } 187 | } 188 | else 189 | { 190 | NSRange subHeaderRange = NSMakeRange(postStartRangeLocation, endRange.location - postStartRangeLocation); 191 | return [header substringWithRange:subHeaderRange]; 192 | } 193 | } 194 | 195 | @end 196 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/HTTPConnection.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class GCDAsyncSocket; 4 | @class HTTPMessage; 5 | @class HTTPServer; 6 | @class WebSocket; 7 | @protocol HTTPResponse; 8 | 9 | 10 | #define HTTPConnectionDidDieNotification @"HTTPConnectionDidDie" 11 | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | #pragma mark - 14 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | @interface HTTPConfig : NSObject 17 | { 18 | HTTPServer __unsafe_unretained *server; 19 | NSString __strong *documentRoot; 20 | dispatch_queue_t queue; 21 | } 22 | 23 | - (id)initWithServer:(HTTPServer *)server documentRoot:(NSString *)documentRoot; 24 | - (id)initWithServer:(HTTPServer *)server documentRoot:(NSString *)documentRoot queue:(dispatch_queue_t)q; 25 | 26 | @property (nonatomic, unsafe_unretained, readonly) HTTPServer *server; 27 | @property (nonatomic, strong, readonly) NSString *documentRoot; 28 | @property (nonatomic, readonly) dispatch_queue_t queue; 29 | 30 | @end 31 | 32 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | #pragma mark - 34 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 35 | 36 | @interface HTTPConnection : NSObject 37 | { 38 | dispatch_queue_t connectionQueue; 39 | GCDAsyncSocket *asyncSocket; 40 | HTTPConfig *config; 41 | 42 | BOOL started; 43 | 44 | HTTPMessage *request; 45 | unsigned int numHeaderLines; 46 | 47 | BOOL sentResponseHeaders; 48 | 49 | NSString *nonce; 50 | long lastNC; 51 | 52 | NSObject *httpResponse; 53 | 54 | NSMutableArray *ranges; 55 | NSMutableArray *ranges_headers; 56 | NSString *ranges_boundry; 57 | int rangeIndex; 58 | 59 | UInt64 requestContentLength; 60 | UInt64 requestContentLengthReceived; 61 | UInt64 requestChunkSize; 62 | UInt64 requestChunkSizeReceived; 63 | 64 | NSMutableArray *responseDataSizes; 65 | } 66 | 67 | - (id)initWithAsyncSocket:(GCDAsyncSocket *)newSocket configuration:(HTTPConfig *)aConfig; 68 | 69 | - (void)start; 70 | - (void)stop; 71 | 72 | - (void)startConnection; 73 | 74 | - (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path; 75 | - (BOOL)expectsRequestBodyFromMethod:(NSString *)method atPath:(NSString *)path; 76 | 77 | - (BOOL)isSecureServer; 78 | - (NSArray *)sslIdentityAndCertificates; 79 | 80 | - (BOOL)isPasswordProtected:(NSString *)path; 81 | - (BOOL)useDigestAccessAuthentication; 82 | - (NSString *)realm; 83 | - (NSString *)passwordForUser:(NSString *)username; 84 | 85 | - (NSDictionary *)parseParams:(NSString *)query; 86 | - (NSDictionary *)parseGetParams; 87 | 88 | - (NSString *)requestURI; 89 | 90 | - (NSArray *)directoryIndexFileNames; 91 | - (NSString *)filePathForURI:(NSString *)path; 92 | - (NSString *)filePathForURI:(NSString *)path allowDirectory:(BOOL)allowDirectory; 93 | - (NSObject *)httpResponseForMethod:(NSString *)method URI:(NSString *)path; 94 | - (WebSocket *)webSocketForURI:(NSString *)path; 95 | 96 | - (void)prepareForBodyWithSize:(UInt64)contentLength; 97 | - (void)processBodyData:(NSData *)postDataChunk; 98 | - (void)finishBody; 99 | 100 | - (void)handleVersionNotSupported:(NSString *)version; 101 | - (void)handleAuthenticationFailed; 102 | - (void)handleResourceNotFound; 103 | - (void)handleInvalidRequest:(NSData *)data; 104 | - (void)handleUnknownMethod:(NSString *)method; 105 | 106 | - (NSData *)preprocessResponse:(HTTPMessage *)response; 107 | - (NSData *)preprocessErrorResponse:(HTTPMessage *)response; 108 | 109 | - (void)finishResponse; 110 | 111 | - (BOOL)shouldDie; 112 | - (void)die; 113 | 114 | @end 115 | 116 | @interface HTTPConnection (AsynchronousHTTPResponse) 117 | - (void)responseHasAvailableData:(NSObject *)sender; 118 | - (void)responseDidAbort:(NSObject *)sender; 119 | @end 120 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/HTTPLogging.h: -------------------------------------------------------------------------------- 1 | /** 2 | * In order to provide fast and flexible logging, this project uses Cocoa Lumberjack. 3 | * 4 | * The Google Code page has a wealth of documentation if you have any questions. 5 | * https://github.com/robbiehanson/CocoaLumberjack 6 | * 7 | * Here's what you need to know concerning how logging is setup for CocoaHTTPServer: 8 | * 9 | * There are 4 log levels: 10 | * - Error 11 | * - Warning 12 | * - Info 13 | * - Verbose 14 | * 15 | * In addition to this, there is a Trace flag that can be enabled. 16 | * When tracing is enabled, it spits out the methods that are being called. 17 | * 18 | * Please note that tracing is separate from the log levels. 19 | * For example, one could set the log level to warning, and enable tracing. 20 | * 21 | * All logging is asynchronous, except errors. 22 | * To use logging within your own custom files, follow the steps below. 23 | * 24 | * Step 1: 25 | * Import this header in your implementation file: 26 | * 27 | * #import "HTTPLogging.h" 28 | * 29 | * Step 2: 30 | * Define your logging level in your implementation file: 31 | * 32 | * // Log levels: off, error, warn, info, verbose 33 | * static const int httpLogLevel = HTTP_LOG_LEVEL_VERBOSE; 34 | * 35 | * If you wish to enable tracing, you could do something like this: 36 | * 37 | * // Debug levels: off, error, warn, info, verbose 38 | * static const int httpLogLevel = HTTP_LOG_LEVEL_INFO | HTTP_LOG_FLAG_TRACE; 39 | * 40 | * Step 3: 41 | * Replace your NSLog statements with HTTPLog statements according to the severity of the message. 42 | * 43 | * NSLog(@"Fatal error, no dohickey found!"); -> HTTPLogError(@"Fatal error, no dohickey found!"); 44 | * 45 | * HTTPLog works exactly the same as NSLog. 46 | * This means you can pass it multiple variables just like NSLog. 47 | **/ 48 | 49 | #import "DDLog.h" 50 | 51 | // Define logging context for every log message coming from the HTTP server. 52 | // The logging context can be extracted from the DDLogMessage from within the logging framework, 53 | // which gives loggers, formatters, and filters the ability to optionally process them differently. 54 | 55 | #define HTTP_LOG_CONTEXT 80 56 | 57 | // Configure log levels. 58 | 59 | #define HTTP_LOG_FLAG_ERROR (1 << 0) // 0...00001 60 | #define HTTP_LOG_FLAG_WARN (1 << 1) // 0...00010 61 | #define HTTP_LOG_FLAG_INFO (1 << 2) // 0...00100 62 | #define HTTP_LOG_FLAG_VERBOSE (1 << 3) // 0...01000 63 | 64 | #define HTTP_LOG_LEVEL_OFF 0 // 0...00000 65 | #define HTTP_LOG_LEVEL_ERROR (HTTP_LOG_LEVEL_OFF | HTTP_LOG_FLAG_ERROR) // 0...00001 66 | #define HTTP_LOG_LEVEL_WARN (HTTP_LOG_LEVEL_ERROR | HTTP_LOG_FLAG_WARN) // 0...00011 67 | #define HTTP_LOG_LEVEL_INFO (HTTP_LOG_LEVEL_WARN | HTTP_LOG_FLAG_INFO) // 0...00111 68 | #define HTTP_LOG_LEVEL_VERBOSE (HTTP_LOG_LEVEL_INFO | HTTP_LOG_FLAG_VERBOSE) // 0...01111 69 | 70 | // Setup fine grained logging. 71 | // The first 4 bits are being used by the standard log levels (0 - 3) 72 | // 73 | // We're going to add tracing, but NOT as a log level. 74 | // Tracing can be turned on and off independently of log level. 75 | 76 | #define HTTP_LOG_FLAG_TRACE (1 << 4) // 0...10000 77 | 78 | // Setup the usual boolean macros. 79 | 80 | #define HTTP_LOG_ERROR (httpLogLevel & HTTP_LOG_FLAG_ERROR) 81 | #define HTTP_LOG_WARN (httpLogLevel & HTTP_LOG_FLAG_WARN) 82 | #define HTTP_LOG_INFO (httpLogLevel & HTTP_LOG_FLAG_INFO) 83 | #define HTTP_LOG_VERBOSE (httpLogLevel & HTTP_LOG_FLAG_VERBOSE) 84 | #define HTTP_LOG_TRACE (httpLogLevel & HTTP_LOG_FLAG_TRACE) 85 | 86 | // Configure asynchronous logging. 87 | // We follow the default configuration, 88 | // but we reserve a special macro to easily disable asynchronous logging for debugging purposes. 89 | 90 | #define HTTP_LOG_ASYNC_ENABLED YES 91 | 92 | #define HTTP_LOG_ASYNC_ERROR ( NO && HTTP_LOG_ASYNC_ENABLED) 93 | #define HTTP_LOG_ASYNC_WARN (YES && HTTP_LOG_ASYNC_ENABLED) 94 | #define HTTP_LOG_ASYNC_INFO (YES && HTTP_LOG_ASYNC_ENABLED) 95 | #define HTTP_LOG_ASYNC_VERBOSE (YES && HTTP_LOG_ASYNC_ENABLED) 96 | #define HTTP_LOG_ASYNC_TRACE (YES && HTTP_LOG_ASYNC_ENABLED) 97 | 98 | // Define logging primitives. 99 | 100 | #define HTTPLogError(frmt, ...) LOG_OBJC_MAYBE(HTTP_LOG_ASYNC_ERROR, httpLogLevel, HTTP_LOG_FLAG_ERROR, \ 101 | HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__) 102 | 103 | #define HTTPLogWarn(frmt, ...) LOG_OBJC_MAYBE(HTTP_LOG_ASYNC_WARN, httpLogLevel, HTTP_LOG_FLAG_WARN, \ 104 | HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__) 105 | 106 | #define HTTPLogInfo(frmt, ...) LOG_OBJC_MAYBE(HTTP_LOG_ASYNC_INFO, httpLogLevel, HTTP_LOG_FLAG_INFO, \ 107 | HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__) 108 | 109 | #define HTTPLogVerbose(frmt, ...) LOG_OBJC_MAYBE(HTTP_LOG_ASYNC_VERBOSE, httpLogLevel, HTTP_LOG_FLAG_VERBOSE, \ 110 | HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__) 111 | 112 | #define HTTPLogTrace() LOG_OBJC_MAYBE(HTTP_LOG_ASYNC_TRACE, httpLogLevel, HTTP_LOG_FLAG_TRACE, \ 113 | HTTP_LOG_CONTEXT, @"%@[%p]: %@", THIS_FILE, self, THIS_METHOD) 114 | 115 | #define HTTPLogTrace2(frmt, ...) LOG_OBJC_MAYBE(HTTP_LOG_ASYNC_TRACE, httpLogLevel, HTTP_LOG_FLAG_TRACE, \ 116 | HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__) 117 | 118 | 119 | #define HTTPLogCError(frmt, ...) LOG_C_MAYBE(HTTP_LOG_ASYNC_ERROR, httpLogLevel, HTTP_LOG_FLAG_ERROR, \ 120 | HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__) 121 | 122 | #define HTTPLogCWarn(frmt, ...) LOG_C_MAYBE(HTTP_LOG_ASYNC_WARN, httpLogLevel, HTTP_LOG_FLAG_WARN, \ 123 | HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__) 124 | 125 | #define HTTPLogCInfo(frmt, ...) LOG_C_MAYBE(HTTP_LOG_ASYNC_INFO, httpLogLevel, HTTP_LOG_FLAG_INFO, \ 126 | HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__) 127 | 128 | #define HTTPLogCVerbose(frmt, ...) LOG_C_MAYBE(HTTP_LOG_ASYNC_VERBOSE, httpLogLevel, HTTP_LOG_FLAG_VERBOSE, \ 129 | HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__) 130 | 131 | #define HTTPLogCTrace() LOG_C_MAYBE(HTTP_LOG_ASYNC_TRACE, httpLogLevel, HTTP_LOG_FLAG_TRACE, \ 132 | HTTP_LOG_CONTEXT, @"%@[%p]: %@", THIS_FILE, self, __FUNCTION__) 133 | 134 | #define HTTPLogCTrace2(frmt, ...) LOG_C_MAYBE(HTTP_LOG_ASYNC_TRACE, httpLogLevel, HTTP_LOG_FLAG_TRACE, \ 135 | HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__) 136 | 137 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/HTTPMessage.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The HTTPMessage class is a simple Objective-C wrapper around Apple's CFHTTPMessage class. 3 | **/ 4 | 5 | #import 6 | 7 | #if TARGET_OS_IPHONE 8 | // Note: You may need to add the CFNetwork Framework to your project 9 | #import 10 | #endif 11 | 12 | #define HTTPVersion1_0 ((NSString *)kCFHTTPVersion1_0) 13 | #define HTTPVersion1_1 ((NSString *)kCFHTTPVersion1_1) 14 | 15 | 16 | @interface HTTPMessage : NSObject 17 | { 18 | CFHTTPMessageRef message; 19 | } 20 | 21 | - (id)initEmptyRequest; 22 | 23 | - (id)initRequestWithMethod:(NSString *)method URL:(NSURL *)url version:(NSString *)version; 24 | 25 | - (id)initResponseWithStatusCode:(NSInteger)code description:(NSString *)description version:(NSString *)version; 26 | 27 | - (BOOL)appendData:(NSData *)data; 28 | 29 | - (BOOL)isHeaderComplete; 30 | 31 | - (NSString *)version; 32 | 33 | - (NSString *)method; 34 | - (NSURL *)url; 35 | 36 | - (NSInteger)statusCode; 37 | 38 | - (NSDictionary *)allHeaderFields; 39 | - (NSString *)headerField:(NSString *)headerField; 40 | 41 | - (void)setHeaderField:(NSString *)headerField value:(NSString *)headerFieldValue; 42 | 43 | - (NSData *)messageData; 44 | 45 | - (NSData *)body; 46 | - (void)setBody:(NSData *)body; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/HTTPMessage.m: -------------------------------------------------------------------------------- 1 | #import "HTTPMessage.h" 2 | 3 | #if ! __has_feature(objc_arc) 4 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 5 | #endif 6 | 7 | 8 | @implementation HTTPMessage 9 | 10 | - (id)initEmptyRequest 11 | { 12 | if ((self = [super init])) 13 | { 14 | message = CFHTTPMessageCreateEmpty(NULL, YES); 15 | } 16 | return self; 17 | } 18 | 19 | - (id)initRequestWithMethod:(NSString *)method URL:(NSURL *)url version:(NSString *)version 20 | { 21 | if ((self = [super init])) 22 | { 23 | message = CFHTTPMessageCreateRequest(NULL, 24 | (__bridge CFStringRef)method, 25 | (__bridge CFURLRef)url, 26 | (__bridge CFStringRef)version); 27 | } 28 | return self; 29 | } 30 | 31 | - (id)initResponseWithStatusCode:(NSInteger)code description:(NSString *)description version:(NSString *)version 32 | { 33 | if ((self = [super init])) 34 | { 35 | message = CFHTTPMessageCreateResponse(NULL, 36 | (CFIndex)code, 37 | (__bridge CFStringRef)description, 38 | (__bridge CFStringRef)version); 39 | } 40 | return self; 41 | } 42 | 43 | - (void)dealloc 44 | { 45 | if (message) 46 | { 47 | CFRelease(message); 48 | } 49 | } 50 | 51 | - (BOOL)appendData:(NSData *)data 52 | { 53 | return CFHTTPMessageAppendBytes(message, [data bytes], [data length]); 54 | } 55 | 56 | - (BOOL)isHeaderComplete 57 | { 58 | return CFHTTPMessageIsHeaderComplete(message); 59 | } 60 | 61 | - (NSString *)version 62 | { 63 | return (__bridge_transfer NSString *)CFHTTPMessageCopyVersion(message); 64 | } 65 | 66 | - (NSString *)method 67 | { 68 | return (__bridge_transfer NSString *)CFHTTPMessageCopyRequestMethod(message); 69 | } 70 | 71 | - (NSURL *)url 72 | { 73 | return (__bridge_transfer NSURL *)CFHTTPMessageCopyRequestURL(message); 74 | } 75 | 76 | - (NSInteger)statusCode 77 | { 78 | return (NSInteger)CFHTTPMessageGetResponseStatusCode(message); 79 | } 80 | 81 | - (NSDictionary *)allHeaderFields 82 | { 83 | return (__bridge_transfer NSDictionary *)CFHTTPMessageCopyAllHeaderFields(message); 84 | } 85 | 86 | - (NSString *)headerField:(NSString *)headerField 87 | { 88 | return (__bridge_transfer NSString *)CFHTTPMessageCopyHeaderFieldValue(message, (__bridge CFStringRef)headerField); 89 | } 90 | 91 | - (void)setHeaderField:(NSString *)headerField value:(NSString *)headerFieldValue 92 | { 93 | CFHTTPMessageSetHeaderFieldValue(message, 94 | (__bridge CFStringRef)headerField, 95 | (__bridge CFStringRef)headerFieldValue); 96 | } 97 | 98 | - (NSData *)messageData 99 | { 100 | return (__bridge_transfer NSData *)CFHTTPMessageCopySerializedMessage(message); 101 | } 102 | 103 | - (NSData *)body 104 | { 105 | return (__bridge_transfer NSData *)CFHTTPMessageCopyBody(message); 106 | } 107 | 108 | - (void)setBody:(NSData *)body 109 | { 110 | CFHTTPMessageSetBody(message, (__bridge CFDataRef)body); 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/HTTPResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @protocol HTTPResponse 5 | 6 | /** 7 | * Returns the length of the data in bytes. 8 | * If you don't know the length in advance, implement the isChunked method and have it return YES. 9 | **/ 10 | - (UInt64)contentLength; 11 | 12 | /** 13 | * The HTTP server supports range requests in order to allow things like 14 | * file download resumption and optimized streaming on mobile devices. 15 | **/ 16 | - (UInt64)offset; 17 | - (void)setOffset:(UInt64)offset; 18 | 19 | /** 20 | * Returns the data for the response. 21 | * You do not have to return data of the exact length that is given. 22 | * You may optionally return data of a lesser length. 23 | * However, you must never return data of a greater length than requested. 24 | * Doing so could disrupt proper support for range requests. 25 | * 26 | * To support asynchronous responses, read the discussion at the bottom of this header. 27 | **/ 28 | - (NSData *)readDataOfLength:(NSUInteger)length; 29 | 30 | /** 31 | * Should only return YES after the HTTPConnection has read all available data. 32 | * That is, all data for the response has been returned to the HTTPConnection via the readDataOfLength method. 33 | **/ 34 | - (BOOL)isDone; 35 | 36 | @optional 37 | 38 | /** 39 | * If you need time to calculate any part of the HTTP response headers (status code or header fields), 40 | * this method allows you to delay sending the headers so that you may asynchronously execute the calculations. 41 | * Simply implement this method and return YES until you have everything you need concerning the headers. 42 | * 43 | * This method ties into the asynchronous response architecture of the HTTPConnection. 44 | * You should read the full discussion at the bottom of this header. 45 | * 46 | * If you return YES from this method, 47 | * the HTTPConnection will wait for you to invoke the responseHasAvailableData method. 48 | * After you do, the HTTPConnection will again invoke this method to see if the response is ready to send the headers. 49 | * 50 | * You should only delay sending the headers until you have everything you need concerning just the headers. 51 | * Asynchronously generating the body of the response is not an excuse to delay sending the headers. 52 | * Instead you should tie into the asynchronous response architecture, and use techniques such as the isChunked method. 53 | * 54 | * Important: You should read the discussion at the bottom of this header. 55 | **/ 56 | - (BOOL)delayResponseHeaders; 57 | 58 | /** 59 | * Status code for response. 60 | * Allows for responses such as redirect (301), etc. 61 | **/ 62 | - (NSInteger)status; 63 | 64 | /** 65 | * If you want to add any extra HTTP headers to the response, 66 | * simply return them in a dictionary in this method. 67 | **/ 68 | - (NSDictionary *)httpHeaders; 69 | 70 | /** 71 | * If you don't know the content-length in advance, 72 | * implement this method in your custom response class and return YES. 73 | * 74 | * Important: You should read the discussion at the bottom of this header. 75 | **/ 76 | - (BOOL)isChunked; 77 | 78 | /** 79 | * This method is called from the HTTPConnection class when the connection is closed, 80 | * or when the connection is finished with the response. 81 | * If your response is asynchronous, you should implement this method so you know not to 82 | * invoke any methods on the HTTPConnection after this method is called (as the connection may be deallocated). 83 | **/ 84 | - (void)connectionDidClose; 85 | 86 | @end 87 | 88 | 89 | /** 90 | * Important notice to those implementing custom asynchronous and/or chunked responses: 91 | * 92 | * HTTPConnection supports asynchronous responses. All you have to do in your custom response class is 93 | * asynchronously generate the response, and invoke HTTPConnection's responseHasAvailableData method. 94 | * You don't have to wait until you have all of the response ready to invoke this method. For example, if you 95 | * generate the response in incremental chunks, you could call responseHasAvailableData after generating 96 | * each chunk. Please see the HTTPAsyncFileResponse class for an example of how to do this. 97 | * 98 | * The normal flow of events for an HTTPConnection while responding to a request is like this: 99 | * - Send http resopnse headers 100 | * - Get data from response via readDataOfLength method. 101 | * - Add data to asyncSocket's write queue. 102 | * - Wait for asyncSocket to notify it that the data has been sent. 103 | * - Get more data from response via readDataOfLength method. 104 | * - ... continue this cycle until the entire response has been sent. 105 | * 106 | * With an asynchronous response, the flow is a little different. 107 | * 108 | * First the HTTPResponse is given the opportunity to postpone sending the HTTP response headers. 109 | * This allows the response to asynchronously execute any code needed to calculate a part of the header. 110 | * An example might be the response needs to generate some custom header fields, 111 | * or perhaps the response needs to look for a resource on network-attached storage. 112 | * Since the network-attached storage may be slow, the response doesn't know whether to send a 200 or 404 yet. 113 | * In situations such as this, the HTTPResponse simply implements the delayResponseHeaders method and returns YES. 114 | * After returning YES from this method, the HTTPConnection will wait until the response invokes its 115 | * responseHasAvailableData method. After this occurs, the HTTPConnection will again query the delayResponseHeaders 116 | * method to see if the response is ready to send the headers. 117 | * This cycle will continue until the delayResponseHeaders method returns NO. 118 | * 119 | * You should only delay sending the response headers until you have everything you need concerning just the headers. 120 | * Asynchronously generating the body of the response is not an excuse to delay sending the headers. 121 | * 122 | * After the response headers have been sent, the HTTPConnection calls your readDataOfLength method. 123 | * You may or may not have any available data at this point. If you don't, then simply return nil. 124 | * You should later invoke HTTPConnection's responseHasAvailableData when you have data to send. 125 | * 126 | * You don't have to keep track of when you return nil in the readDataOfLength method, or how many times you've invoked 127 | * responseHasAvailableData. Just simply call responseHasAvailableData whenever you've generated new data, and 128 | * return nil in your readDataOfLength whenever you don't have any available data in the requested range. 129 | * HTTPConnection will automatically detect when it should be requesting new data and will act appropriately. 130 | * 131 | * It's important that you also keep in mind that the HTTP server supports range requests. 132 | * The setOffset method is mandatory, and should not be ignored. 133 | * Make sure you take into account the offset within the readDataOfLength method. 134 | * You should also be aware that the HTTPConnection automatically sorts any range requests. 135 | * So if your setOffset method is called with a value of 100, then you can safely release bytes 0-99. 136 | * 137 | * HTTPConnection can also help you keep your memory footprint small. 138 | * Imagine you're dynamically generating a 10 MB response. You probably don't want to load all this data into 139 | * RAM, and sit around waiting for HTTPConnection to slowly send it out over the network. All you need to do 140 | * is pay attention to when HTTPConnection requests more data via readDataOfLength. This is because HTTPConnection 141 | * will never allow asyncSocket's write queue to get much bigger than READ_CHUNKSIZE bytes. You should 142 | * consider how you might be able to take advantage of this fact to generate your asynchronous response on demand, 143 | * while at the same time keeping your memory footprint small, and your application lightning fast. 144 | * 145 | * If you don't know the content-length in advanced, you should also implement the isChunked method. 146 | * This means the response will not include a Content-Length header, and will instead use "Transfer-Encoding: chunked". 147 | * There's a good chance that if your response is asynchronous and dynamic, it's also chunked. 148 | * If your response is chunked, you don't need to worry about range requests. 149 | **/ 150 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/HTTPServer.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class GCDAsyncSocket; 4 | @class WebSocket; 5 | 6 | #if TARGET_OS_IPHONE 7 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 // iPhone 4.0 8 | #define IMPLEMENTED_PROTOCOLS 9 | #else 10 | #define IMPLEMENTED_PROTOCOLS 11 | #endif 12 | #else 13 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 // Mac OS X 10.6 14 | #define IMPLEMENTED_PROTOCOLS 15 | #else 16 | #define IMPLEMENTED_PROTOCOLS 17 | #endif 18 | #endif 19 | 20 | 21 | @interface HTTPServer : NSObject IMPLEMENTED_PROTOCOLS 22 | { 23 | // Underlying asynchronous TCP/IP socket 24 | GCDAsyncSocket *asyncSocket; 25 | 26 | // Dispatch queues 27 | dispatch_queue_t serverQueue; 28 | dispatch_queue_t connectionQueue; 29 | void *IsOnServerQueueKey; 30 | void *IsOnConnectionQueueKey; 31 | 32 | // HTTP server configuration 33 | NSString *documentRoot; 34 | Class connectionClass; 35 | NSString *interface; 36 | UInt16 port; 37 | 38 | // NSNetService and related variables 39 | NSNetService *netService; 40 | NSString *domain; 41 | NSString *type; 42 | NSString *name; 43 | NSString *publishedName; 44 | NSDictionary *txtRecordDictionary; 45 | 46 | // Connection management 47 | NSMutableArray *connections; 48 | NSMutableArray *webSockets; 49 | NSLock *connectionsLock; 50 | NSLock *webSocketsLock; 51 | 52 | BOOL isRunning; 53 | } 54 | 55 | /** 56 | * Specifies the document root to serve files from. 57 | * For example, if you set this to "/Users//Sites", 58 | * then it will serve files out of the local Sites directory (including subdirectories). 59 | * 60 | * The default value is nil. 61 | * The default server configuration will not serve any files until this is set. 62 | * 63 | * If you change the documentRoot while the server is running, 64 | * the change will affect future incoming http connections. 65 | **/ 66 | - (NSString *)documentRoot; 67 | - (void)setDocumentRoot:(NSString *)value; 68 | 69 | /** 70 | * The connection class is the class used to handle incoming HTTP connections. 71 | * 72 | * The default value is [HTTPConnection class]. 73 | * You can override HTTPConnection, and then set this to [MyHTTPConnection class]. 74 | * 75 | * If you change the connectionClass while the server is running, 76 | * the change will affect future incoming http connections. 77 | **/ 78 | - (Class)connectionClass; 79 | - (void)setConnectionClass:(Class)value; 80 | 81 | /** 82 | * Set what interface you'd like the server to listen on. 83 | * By default this is nil, which causes the server to listen on all available interfaces like en1, wifi etc. 84 | * 85 | * The interface may be specified by name (e.g. "en1" or "lo0") or by IP address (e.g. "192.168.4.34"). 86 | * You may also use the special strings "localhost" or "loopback" to specify that 87 | * the socket only accept connections from the local machine. 88 | **/ 89 | - (NSString *)interface; 90 | - (void)setInterface:(NSString *)value; 91 | 92 | /** 93 | * The port number to run the HTTP server on. 94 | * 95 | * The default port number is zero, meaning the server will automatically use any available port. 96 | * This is the recommended port value, as it avoids possible port conflicts with other applications. 97 | * Technologies such as Bonjour can be used to allow other applications to automatically discover the port number. 98 | * 99 | * Note: As is common on most OS's, you need root privledges to bind to port numbers below 1024. 100 | * 101 | * You can change the port property while the server is running, but it won't affect the running server. 102 | * To actually change the port the server is listening for connections on you'll need to restart the server. 103 | * 104 | * The listeningPort method will always return the port number the running server is listening for connections on. 105 | * If the server is not running this method returns 0. 106 | **/ 107 | - (UInt16)port; 108 | - (UInt16)listeningPort; 109 | - (void)setPort:(UInt16)value; 110 | 111 | /** 112 | * Bonjour domain for publishing the service. 113 | * The default value is "local.". 114 | * 115 | * Note: Bonjour publishing requires you set a type. 116 | * 117 | * If you change the domain property after the bonjour service has already been published (server already started), 118 | * you'll need to invoke the republishBonjour method to update the broadcasted bonjour service. 119 | **/ 120 | - (NSString *)domain; 121 | - (void)setDomain:(NSString *)value; 122 | 123 | /** 124 | * Bonjour name for publishing the service. 125 | * The default value is "". 126 | * 127 | * If using an empty string ("") for the service name when registering, 128 | * the system will automatically use the "Computer Name". 129 | * Using an empty string will also handle name conflicts 130 | * by automatically appending a digit to the end of the name. 131 | * 132 | * Note: Bonjour publishing requires you set a type. 133 | * 134 | * If you change the name after the bonjour service has already been published (server already started), 135 | * you'll need to invoke the republishBonjour method to update the broadcasted bonjour service. 136 | * 137 | * The publishedName method will always return the actual name that was published via the bonjour service. 138 | * If the service is not running this method returns nil. 139 | **/ 140 | - (NSString *)name; 141 | - (NSString *)publishedName; 142 | - (void)setName:(NSString *)value; 143 | 144 | /** 145 | * Bonjour type for publishing the service. 146 | * The default value is nil. 147 | * The service will not be published via bonjour unless the type is set. 148 | * 149 | * If you wish to publish the service as a traditional HTTP server, you should set the type to be "_http._tcp.". 150 | * 151 | * If you change the type after the bonjour service has already been published (server already started), 152 | * you'll need to invoke the republishBonjour method to update the broadcasted bonjour service. 153 | **/ 154 | - (NSString *)type; 155 | - (void)setType:(NSString *)value; 156 | 157 | /** 158 | * Republishes the service via bonjour if the server is running. 159 | * If the service was not previously published, this method will publish it (if the server is running). 160 | **/ 161 | - (void)republishBonjour; 162 | 163 | /** 164 | * 165 | **/ 166 | - (NSDictionary *)TXTRecordDictionary; 167 | - (void)setTXTRecordDictionary:(NSDictionary *)dict; 168 | 169 | /** 170 | * Attempts to starts the server on the configured port, interface, etc. 171 | * 172 | * If an error occurs, this method returns NO and sets the errPtr (if given). 173 | * Otherwise returns YES on success. 174 | * 175 | * Some examples of errors that might occur: 176 | * - You specified the server listen on a port which is already in use by another application. 177 | * - You specified the server listen on a port number below 1024, which requires root priviledges. 178 | * 179 | * Code Example: 180 | * 181 | * NSError *err = nil; 182 | * if (![httpServer start:&err]) 183 | * { 184 | * NSLog(@"Error starting http server: %@", err); 185 | * } 186 | **/ 187 | - (BOOL)start:(NSError **)errPtr; 188 | 189 | /** 190 | * Stops the server, preventing it from accepting any new connections. 191 | * You may specify whether or not you want to close the existing client connections. 192 | * 193 | * The default stop method (with no arguments) will close any existing connections. (It invokes [self stop:NO]) 194 | **/ 195 | - (void)stop; 196 | - (void)stop:(BOOL)keepExistingConnections; 197 | 198 | - (BOOL)isRunning; 199 | 200 | - (void)addWebSocket:(WebSocket *)ws; 201 | 202 | - (NSUInteger)numberOfHTTPConnections; 203 | - (NSUInteger)numberOfWebSocketConnections; 204 | 205 | @end 206 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Mime/MultipartFormDataParser.h: -------------------------------------------------------------------------------- 1 | 2 | #import "MultipartMessageHeader.h" 3 | 4 | /* 5 | Part one: http://tools.ietf.org/html/rfc2045 (Format of Internet Message Bodies) 6 | Part two: http://tools.ietf.org/html/rfc2046 (Media Types) 7 | Part three: http://tools.ietf.org/html/rfc2047 (Message Header Extensions for Non-ASCII Text) 8 | Part four: http://tools.ietf.org/html/rfc4289 (Registration Procedures) 9 | Part five: http://tools.ietf.org/html/rfc2049 (Conformance Criteria and Examples) 10 | 11 | Internet message format: http://tools.ietf.org/html/rfc2822 12 | 13 | Multipart/form-data http://tools.ietf.org/html/rfc2388 14 | */ 15 | 16 | @class MultipartFormDataParser; 17 | 18 | //----------------------------------------------------------------- 19 | // protocol MultipartFormDataParser 20 | //----------------------------------------------------------------- 21 | 22 | @protocol MultipartFormDataParserDelegate 23 | @optional 24 | - (void) processContent:(NSData*) data WithHeader:(MultipartMessageHeader*) header; 25 | - (void) processEndOfPartWithHeader:(MultipartMessageHeader*) header; 26 | - (void) processPreambleData:(NSData*) data; 27 | - (void) processEpilogueData:(NSData*) data; 28 | - (void) processStartOfPartWithHeader:(MultipartMessageHeader*) header; 29 | @end 30 | 31 | //----------------------------------------------------------------- 32 | // interface MultipartFormDataParser 33 | //----------------------------------------------------------------- 34 | 35 | @interface MultipartFormDataParser : NSObject { 36 | NSMutableData* pendingData; 37 | NSData* boundaryData; 38 | MultipartMessageHeader* currentHeader; 39 | 40 | BOOL waitingForCRLF; 41 | BOOL reachedEpilogue; 42 | BOOL processedPreamble; 43 | BOOL checkForContentEnd; 44 | 45 | #if __has_feature(objc_arc_weak) 46 | __weak id delegate; 47 | #else 48 | __unsafe_unretained id delegate; 49 | #endif 50 | int currentEncoding; 51 | NSStringEncoding formEncoding; 52 | } 53 | 54 | - (BOOL) appendData:(NSData*) data; 55 | 56 | - (id) initWithBoundary:(NSString*) boundary formEncoding:(NSStringEncoding) formEncoding; 57 | 58 | #if __has_feature(objc_arc_weak) 59 | @property(weak, readwrite) id delegate; 60 | #else 61 | @property(unsafe_unretained, readwrite) id delegate; 62 | #endif 63 | @property(readwrite) NSStringEncoding formEncoding; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Mime/MultipartMessageHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // MultipartMessagePart.h 3 | // HttpServer 4 | // 5 | // Created by Валерий Гаврилов on 29.03.12. 6 | // Copyright (c) 2012 LLC "Online Publishing Partners" (onlinepp.ru). All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | //----------------------------------------------------------------- 13 | // interface MultipartMessageHeader 14 | //----------------------------------------------------------------- 15 | enum { 16 | contentTransferEncoding_unknown, 17 | contentTransferEncoding_7bit, 18 | contentTransferEncoding_8bit, 19 | contentTransferEncoding_binary, 20 | contentTransferEncoding_base64, 21 | contentTransferEncoding_quotedPrintable, 22 | }; 23 | 24 | @interface MultipartMessageHeader : NSObject { 25 | NSMutableDictionary* fields; 26 | int encoding; 27 | NSString* contentDispositionName; 28 | } 29 | @property (strong,readonly) NSDictionary* fields; 30 | @property (readonly) int encoding; 31 | 32 | - (id) initWithData:(NSData*) data formEncoding:(NSStringEncoding) encoding; 33 | @end 34 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Mime/MultipartMessageHeader.m: -------------------------------------------------------------------------------- 1 | // 2 | // MultipartMessagePart.m 3 | // HttpServer 4 | // 5 | // Created by Валерий Гаврилов on 29.03.12. 6 | // Copyright (c) 2012 LLC "Online Publishing Partners" (onlinepp.ru). All rights reserved. 7 | 8 | #import "MultipartMessageHeader.h" 9 | #import "MultipartMessageHeaderField.h" 10 | 11 | #import "HTTPLogging.h" 12 | 13 | //----------------------------------------------------------------- 14 | #pragma mark log level 15 | 16 | #ifdef DEBUG 17 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; 18 | #else 19 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; 20 | #endif 21 | 22 | //----------------------------------------------------------------- 23 | // implementation MultipartMessageHeader 24 | //----------------------------------------------------------------- 25 | 26 | 27 | @implementation MultipartMessageHeader 28 | @synthesize fields,encoding; 29 | 30 | 31 | - (id) initWithData:(NSData *)data formEncoding:(NSStringEncoding) formEncoding { 32 | if( nil == (self = [super init]) ) { 33 | return self; 34 | } 35 | 36 | fields = [[NSMutableDictionary alloc] initWithCapacity:1]; 37 | 38 | // In case encoding is not mentioned, 39 | encoding = contentTransferEncoding_unknown; 40 | 41 | char* bytes = (char*)data.bytes; 42 | NSUInteger length = data.length; 43 | int offset = 0; 44 | 45 | // split header into header fields, separated by \r\n 46 | uint16_t fields_separator = 0x0A0D; // \r\n 47 | while( offset < length - 2 ) { 48 | 49 | // the !isspace condition is to support header unfolding 50 | if( (*(uint16_t*) (bytes+offset) == fields_separator) && ((offset == length - 2) || !(isspace(bytes[offset+2])) )) { 51 | NSData* fieldData = [NSData dataWithBytesNoCopy:bytes length:offset freeWhenDone:NO]; 52 | MultipartMessageHeaderField* field = [[MultipartMessageHeaderField alloc] initWithData: fieldData contentEncoding:formEncoding]; 53 | if( field ) { 54 | [fields setObject:field forKey:field.name]; 55 | HTTPLogVerbose(@"MultipartFormDataParser: Processed Header field '%@'",field.name); 56 | } 57 | else { 58 | NSString* fieldStr = [[NSString alloc] initWithData:fieldData encoding:NSASCIIStringEncoding]; 59 | HTTPLogWarn(@"MultipartFormDataParser: Failed to parse MIME header field. Input ASCII string:%@",fieldStr); 60 | } 61 | 62 | // move to the next header field 63 | bytes += offset + 2; 64 | length -= offset + 2; 65 | offset = 0; 66 | continue; 67 | } 68 | ++ offset; 69 | } 70 | 71 | if( !fields.count ) { 72 | // it was an empty header. 73 | // we have to set default values. 74 | // default header. 75 | [fields setObject:@"text/plain" forKey:@"Content-Type"]; 76 | } 77 | 78 | return self; 79 | } 80 | 81 | - (NSString *)description { 82 | return [NSString stringWithFormat:@"%@",fields]; 83 | } 84 | 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Mime/MultipartMessageHeaderField.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | //----------------------------------------------------------------- 5 | // interface MultipartMessageHeaderField 6 | //----------------------------------------------------------------- 7 | 8 | @interface MultipartMessageHeaderField : NSObject { 9 | NSString* name; 10 | NSString* value; 11 | NSMutableDictionary* params; 12 | } 13 | 14 | @property (strong, readonly) NSString* value; 15 | @property (strong, readonly) NSDictionary* params; 16 | @property (strong, readonly) NSString* name; 17 | 18 | //- (id) initWithLine:(NSString*) line; 19 | //- (id) initWithName:(NSString*) paramName value:(NSString*) paramValue; 20 | 21 | - (id) initWithData:(NSData*) data contentEncoding:(NSStringEncoding) encoding; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Mime/MultipartMessageHeaderField.m: -------------------------------------------------------------------------------- 1 | 2 | #import "MultipartMessageHeaderField.h" 3 | #import "HTTPLogging.h" 4 | 5 | //----------------------------------------------------------------- 6 | #pragma mark log level 7 | 8 | #ifdef DEBUG 9 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; 10 | #else 11 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; 12 | #endif 13 | 14 | 15 | // helpers 16 | int findChar(const char* str,NSUInteger length, char c); 17 | NSString* extractParamValue(const char* bytes, NSUInteger length, NSStringEncoding encoding); 18 | 19 | //----------------------------------------------------------------- 20 | // interface MultipartMessageHeaderField (private) 21 | //----------------------------------------------------------------- 22 | 23 | 24 | @interface MultipartMessageHeaderField (private) 25 | -(BOOL) parseHeaderValueBytes:(char*) bytes length:(NSUInteger) length encoding:(NSStringEncoding) encoding; 26 | @end 27 | 28 | 29 | //----------------------------------------------------------------- 30 | // implementation MultipartMessageHeaderField 31 | //----------------------------------------------------------------- 32 | 33 | @implementation MultipartMessageHeaderField 34 | @synthesize name,value,params; 35 | 36 | - (id) initWithData:(NSData *)data contentEncoding:(NSStringEncoding)encoding { 37 | params = [[NSMutableDictionary alloc] initWithCapacity:1]; 38 | 39 | char* bytes = (char*)data.bytes; 40 | NSUInteger length = data.length; 41 | 42 | int separatorOffset = findChar(bytes, length, ':'); 43 | if( (-1 == separatorOffset) || (separatorOffset >= length-2) ) { 44 | HTTPLogError(@"MultipartFormDataParser: Bad format.No colon in field header."); 45 | // tear down 46 | return nil; 47 | } 48 | 49 | // header name is always ascii encoded; 50 | name = [[NSString alloc] initWithBytes: bytes length: separatorOffset encoding: NSASCIIStringEncoding]; 51 | if( nil == name ) { 52 | HTTPLogError(@"MultipartFormDataParser: Bad MIME header name."); 53 | // tear down 54 | return nil; 55 | } 56 | 57 | // skip the separator and the next ' ' symbol 58 | bytes += separatorOffset + 2; 59 | length -= separatorOffset + 2; 60 | 61 | separatorOffset = findChar(bytes, length, ';'); 62 | if( separatorOffset == -1 ) { 63 | // couldn't find ';', means we don't have extra params here. 64 | value = [[NSString alloc] initWithBytes:bytes length: length encoding:encoding]; 65 | 66 | if( nil == value ) { 67 | HTTPLogError(@"MultipartFormDataParser: Bad MIME header value for header name: '%@'",name); 68 | // tear down 69 | return nil; 70 | } 71 | return self; 72 | } 73 | 74 | value = [[NSString alloc] initWithBytes:bytes length: separatorOffset encoding:encoding]; 75 | HTTPLogVerbose(@"MultipartFormDataParser: Processing header field '%@' : '%@'",name,value); 76 | // skipe the separator and the next ' ' symbol 77 | bytes += separatorOffset + 2; 78 | length -= separatorOffset + 2; 79 | 80 | // parse the "params" part of the header 81 | if( ![self parseHeaderValueBytes:bytes length:length encoding:encoding] ) { 82 | NSString* paramsStr = [[NSString alloc] initWithBytes:bytes length:length encoding:NSASCIIStringEncoding]; 83 | HTTPLogError(@"MultipartFormDataParser: Bad params for header with name '%@' and value '%@'",name,value); 84 | HTTPLogError(@"MultipartFormDataParser: Params str: %@",paramsStr); 85 | 86 | return nil; 87 | } 88 | return self; 89 | } 90 | 91 | -(BOOL) parseHeaderValueBytes:(char*) bytes length:(NSUInteger) length encoding:(NSStringEncoding) encoding { 92 | int offset = 0; 93 | NSString* currentParam = nil; 94 | BOOL insideQuote = NO; 95 | while( offset < length ) { 96 | if( bytes[offset] == '\"' ) { 97 | if( !offset || bytes[offset-1] != '\\' ) { 98 | insideQuote = !insideQuote; 99 | } 100 | } 101 | 102 | // skip quoted symbols 103 | if( insideQuote ) { 104 | ++ offset; 105 | continue; 106 | } 107 | if( bytes[offset] == '=' ) { 108 | if( currentParam ) { 109 | // found '=' before terminating previous param. 110 | return NO; 111 | } 112 | currentParam = [[NSString alloc] initWithBytes:bytes length:offset encoding:NSASCIIStringEncoding]; 113 | 114 | bytes+=offset + 1; 115 | length -= offset + 1; 116 | offset = 0; 117 | continue; 118 | } 119 | if( bytes[offset] == ';' ) { 120 | if( !currentParam ) { 121 | // found ; before stating '='. 122 | HTTPLogError(@"MultipartFormDataParser: Unexpected ';' when parsing header"); 123 | return NO; 124 | } 125 | NSString* paramValue = extractParamValue(bytes, offset,encoding); 126 | if( nil == paramValue ) { 127 | HTTPLogWarn(@"MultipartFormDataParser: Failed to exctract paramValue for key %@ in header %@",currentParam,name); 128 | } 129 | else { 130 | #ifdef DEBUG 131 | if( [params objectForKey:currentParam] ) { 132 | HTTPLogWarn(@"MultipartFormDataParser: param %@ mentioned more then once in header %@",currentParam,name); 133 | } 134 | #endif 135 | [params setObject:paramValue forKey:currentParam]; 136 | HTTPLogVerbose(@"MultipartFormDataParser: header param: %@ = %@",currentParam,paramValue); 137 | } 138 | 139 | currentParam = nil; 140 | 141 | // ';' separator has ' ' following, skip them. 142 | bytes+=offset + 2; 143 | length -= offset + 2; 144 | offset = 0; 145 | } 146 | ++ offset; 147 | } 148 | 149 | // add last param 150 | if( insideQuote ) { 151 | HTTPLogWarn(@"MultipartFormDataParser: unterminated quote in header %@",name); 152 | // return YES; 153 | } 154 | if( currentParam ) { 155 | NSString* paramValue = extractParamValue(bytes, length, encoding); 156 | 157 | if( nil == paramValue ) { 158 | HTTPLogError(@"MultipartFormDataParser: Failed to exctract paramValue for key %@ in header %@",currentParam,name); 159 | } 160 | 161 | #ifdef DEBUG 162 | if( [params objectForKey:currentParam] ) { 163 | HTTPLogWarn(@"MultipartFormDataParser: param %@ mentioned more then once in one header",currentParam); 164 | } 165 | #endif 166 | [params setObject:paramValue forKey:currentParam]; 167 | HTTPLogVerbose(@"MultipartFormDataParser: header param: %@ = %@",currentParam,paramValue); 168 | currentParam = nil; 169 | } 170 | 171 | return YES; 172 | } 173 | 174 | - (NSString *)description { 175 | return [NSString stringWithFormat:@"%@:%@\n params: %@",name,value,params]; 176 | } 177 | 178 | @end 179 | 180 | int findChar(const char* str, NSUInteger length, char c) { 181 | int offset = 0; 182 | while( offset < length ) { 183 | if( str[offset] == c ) 184 | return offset; 185 | ++ offset; 186 | } 187 | return -1; 188 | } 189 | 190 | NSString* extractParamValue(const char* bytes, NSUInteger length, NSStringEncoding encoding) { 191 | if( !length ) 192 | return nil; 193 | NSMutableString* value = nil; 194 | 195 | if( bytes[0] == '"' ) { 196 | // values may be quoted. Strip the quotes to get what we need. 197 | value = [[NSMutableString alloc] initWithBytes:bytes + 1 length: length - 2 encoding:encoding]; 198 | } 199 | else { 200 | value = [[NSMutableString alloc] initWithBytes:bytes length: length encoding:encoding]; 201 | } 202 | // restore escaped symbols 203 | NSRange range= [value rangeOfString:@"\\"]; 204 | while ( range.length ) { 205 | [value deleteCharactersInRange:range]; 206 | range.location ++; 207 | range = [value rangeOfString:@"\\" options:NSLiteralSearch range: range]; 208 | } 209 | return value; 210 | } 211 | 212 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Responses/HTTPAsyncFileResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPResponse.h" 3 | 4 | @class HTTPConnection; 5 | 6 | /** 7 | * This is an asynchronous version of HTTPFileResponse. 8 | * It reads data from the given file asynchronously via GCD. 9 | * 10 | * It may be overriden to allow custom post-processing of the data that has been read from the file. 11 | * An example of this is the HTTPDynamicFileResponse class. 12 | **/ 13 | 14 | @interface HTTPAsyncFileResponse : NSObject 15 | { 16 | HTTPConnection *connection; 17 | 18 | NSString *filePath; 19 | UInt64 fileLength; 20 | UInt64 fileOffset; // File offset as pertains to data given to connection 21 | UInt64 readOffset; // File offset as pertains to data read from file (but maybe not returned to connection) 22 | 23 | BOOL aborted; 24 | 25 | NSData *data; 26 | 27 | int fileFD; 28 | void *readBuffer; 29 | NSUInteger readBufferSize; // Malloced size of readBuffer 30 | NSUInteger readBufferOffset; // Offset within readBuffer where the end of existing data is 31 | NSUInteger readRequestLength; 32 | dispatch_queue_t readQueue; 33 | dispatch_source_t readSource; 34 | BOOL readSourceSuspended; 35 | } 36 | 37 | - (id)initWithFilePath:(NSString *)filePath forConnection:(HTTPConnection *)connection; 38 | - (NSString *)filePath; 39 | 40 | @end 41 | 42 | /** 43 | * Explanation of Variables (excluding those that are obvious) 44 | * 45 | * fileOffset 46 | * This is the number of bytes that have been returned to the connection via the readDataOfLength method. 47 | * If 1KB of data has been read from the file, but none of that data has yet been returned to the connection, 48 | * then the fileOffset variable remains at zero. 49 | * This variable is used in the calculation of the isDone method. 50 | * Only after all data has been returned to the connection are we actually done. 51 | * 52 | * readOffset 53 | * Represents the offset of the file descriptor. 54 | * In other words, the file position indidcator for our read stream. 55 | * It might be easy to think of it as the total number of bytes that have been read from the file. 56 | * However, this isn't entirely accurate, as the setOffset: method may have caused us to 57 | * jump ahead in the file (lseek). 58 | * 59 | * readBuffer 60 | * Malloc'd buffer to hold data read from the file. 61 | * 62 | * readBufferSize 63 | * Total allocation size of malloc'd buffer. 64 | * 65 | * readBufferOffset 66 | * Represents the position in the readBuffer where we should store new bytes. 67 | * 68 | * readRequestLength 69 | * The total number of bytes that were requested from the connection. 70 | * It's OK if we return a lesser number of bytes to the connection. 71 | * It's NOT OK if we return a greater number of bytes to the connection. 72 | * Doing so would disrupt proper support for range requests. 73 | * If, however, the response is chunked then we don't need to worry about this. 74 | * Chunked responses inheritly don't support range requests. 75 | **/ 76 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Responses/HTTPDataResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPResponse.h" 3 | 4 | 5 | @interface HTTPDataResponse : NSObject 6 | { 7 | NSUInteger offset; 8 | NSData *data; 9 | } 10 | 11 | - (id)initWithData:(NSData *)data; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Responses/HTTPDataResponse.m: -------------------------------------------------------------------------------- 1 | #import "HTTPDataResponse.h" 2 | #import "HTTPLogging.h" 3 | 4 | #if ! __has_feature(objc_arc) 5 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 6 | #endif 7 | 8 | // Log levels : off, error, warn, info, verbose 9 | // Other flags: trace 10 | static const int httpLogLevel = HTTP_LOG_LEVEL_OFF; // | HTTP_LOG_FLAG_TRACE; 11 | 12 | 13 | @implementation HTTPDataResponse 14 | 15 | - (id)initWithData:(NSData *)dataParam 16 | { 17 | if((self = [super init])) 18 | { 19 | HTTPLogTrace(); 20 | 21 | offset = 0; 22 | data = dataParam; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)dealloc 28 | { 29 | HTTPLogTrace(); 30 | 31 | } 32 | 33 | - (UInt64)contentLength 34 | { 35 | UInt64 result = (UInt64)[data length]; 36 | 37 | HTTPLogTrace2(@"%@[%p]: contentLength - %llu", THIS_FILE, self, result); 38 | 39 | return result; 40 | } 41 | 42 | - (UInt64)offset 43 | { 44 | HTTPLogTrace(); 45 | 46 | return offset; 47 | } 48 | 49 | - (void)setOffset:(UInt64)offsetParam 50 | { 51 | HTTPLogTrace2(@"%@[%p]: setOffset:%lu", THIS_FILE, self, (unsigned long)offset); 52 | 53 | offset = (NSUInteger)offsetParam; 54 | } 55 | 56 | - (NSData *)readDataOfLength:(NSUInteger)lengthParameter 57 | { 58 | HTTPLogTrace2(@"%@[%p]: readDataOfLength:%lu", THIS_FILE, self, (unsigned long)lengthParameter); 59 | 60 | NSUInteger remaining = [data length] - offset; 61 | NSUInteger length = lengthParameter < remaining ? lengthParameter : remaining; 62 | 63 | void *bytes = (void *)([data bytes] + offset); 64 | 65 | offset += length; 66 | 67 | return [NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:NO]; 68 | } 69 | 70 | - (BOOL)isDone 71 | { 72 | BOOL result = (offset == [data length]); 73 | 74 | HTTPLogTrace2(@"%@[%p]: isDone - %@", THIS_FILE, self, (result ? @"YES" : @"NO")); 75 | 76 | return result; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Responses/HTTPDynamicFileResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPResponse.h" 3 | #import "HTTPAsyncFileResponse.h" 4 | 5 | /** 6 | * This class is designed to assist with dynamic content. 7 | * Imagine you have a file that you want to make dynamic: 8 | * 9 | * 10 | * 11 | *

ComputerName Control Panel

12 | * ... 13 | *
  • System Time: SysTime
  • 14 | * 15 | * 16 | * 17 | * Now you could generate the entire file in Objective-C, 18 | * but this would be a horribly tedious process. 19 | * Beside, you want to design the file with professional tools to make it look pretty. 20 | * 21 | * So all you have to do is escape your dynamic content like this: 22 | * 23 | * ... 24 | *

    %%ComputerName%% Control Panel

    25 | * ... 26 | *
  • System Time: %%SysTime%%
  • 27 | * 28 | * And then you create an instance of this class with: 29 | * 30 | * - separator = @"%%" 31 | * - replacementDictionary = { "ComputerName"="Black MacBook", "SysTime"="2010-04-30 03:18:24" } 32 | * 33 | * This class will then perform the replacements for you, on the fly, as it reads the file data. 34 | * This class is also asynchronous, so it will perform the file IO using its own GCD queue. 35 | * 36 | * All keys for the replacementDictionary must be NSString's. 37 | * Values for the replacementDictionary may be NSString's, or any object that 38 | * returns what you want when its description method is invoked. 39 | **/ 40 | 41 | @interface HTTPDynamicFileResponse : HTTPAsyncFileResponse 42 | { 43 | NSData *separator; 44 | NSDictionary *replacementDict; 45 | } 46 | 47 | - (id)initWithFilePath:(NSString *)filePath 48 | forConnection:(HTTPConnection *)connection 49 | separator:(NSString *)separatorStr 50 | replacementDictionary:(NSDictionary *)dictionary; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Responses/HTTPDynamicFileResponse.m: -------------------------------------------------------------------------------- 1 | #import "HTTPDynamicFileResponse.h" 2 | #import "HTTPConnection.h" 3 | #import "HTTPLogging.h" 4 | 5 | #if ! __has_feature(objc_arc) 6 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 7 | #endif 8 | 9 | // Log levels : off, error, warn, info, verbose 10 | // Other flags: trace 11 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; // | HTTP_LOG_FLAG_TRACE; 12 | 13 | #define NULL_FD -1 14 | 15 | 16 | @implementation HTTPDynamicFileResponse 17 | 18 | - (id)initWithFilePath:(NSString *)fpath 19 | forConnection:(HTTPConnection *)parent 20 | separator:(NSString *)separatorStr 21 | replacementDictionary:(NSDictionary *)dict 22 | { 23 | if ((self = [super initWithFilePath:fpath forConnection:parent])) 24 | { 25 | HTTPLogTrace(); 26 | 27 | separator = [separatorStr dataUsingEncoding:NSUTF8StringEncoding]; 28 | replacementDict = dict; 29 | } 30 | return self; 31 | } 32 | 33 | - (BOOL)isChunked 34 | { 35 | HTTPLogTrace(); 36 | 37 | return YES; 38 | } 39 | 40 | - (UInt64)contentLength 41 | { 42 | // This method shouldn't be called since we're using a chunked response. 43 | // We override it just to be safe. 44 | 45 | HTTPLogTrace(); 46 | 47 | return 0; 48 | } 49 | 50 | - (void)setOffset:(UInt64)offset 51 | { 52 | // This method shouldn't be called since we're using a chunked response. 53 | // We override it just to be safe. 54 | 55 | HTTPLogTrace(); 56 | } 57 | 58 | - (BOOL)isDone 59 | { 60 | BOOL result = (readOffset == fileLength) && (readBufferOffset == 0); 61 | 62 | HTTPLogTrace2(@"%@[%p]: isDone - %@", THIS_FILE, self, (result ? @"YES" : @"NO")); 63 | 64 | return result; 65 | } 66 | 67 | - (void)processReadBuffer 68 | { 69 | HTTPLogTrace(); 70 | 71 | // At this point, the readBuffer has readBufferOffset bytes available. 72 | // This method is in charge of updating the readBufferOffset. 73 | 74 | NSUInteger bufLen = readBufferOffset; 75 | NSUInteger sepLen = [separator length]; 76 | 77 | // We're going to start looking for the separator at the beginning of the buffer, 78 | // and stop when we get to the point where the separator would no longer fit in the buffer. 79 | 80 | NSUInteger offset = 0; 81 | NSUInteger stopOffset = (bufLen > sepLen) ? bufLen - sepLen + 1 : 0; 82 | 83 | // In order to do the replacement, we need to find the starting and ending separator. 84 | // For example: 85 | // 86 | // %%USER_NAME%% 87 | // 88 | // Where "%%" is the separator. 89 | 90 | BOOL found1 = NO; 91 | BOOL found2 = NO; 92 | 93 | NSUInteger s1 = 0; 94 | NSUInteger s2 = 0; 95 | 96 | const void *sep = [separator bytes]; 97 | 98 | while (offset < stopOffset) 99 | { 100 | const void *subBuffer = readBuffer + offset; 101 | 102 | if (memcmp(subBuffer, sep, sepLen) == 0) 103 | { 104 | if (!found1) 105 | { 106 | // Found the first separator 107 | 108 | found1 = YES; 109 | s1 = offset; 110 | offset += sepLen; 111 | 112 | HTTPLogVerbose(@"%@[%p]: Found s1 at %lu", THIS_FILE, self, (unsigned long)s1); 113 | } 114 | else 115 | { 116 | // Found the second separator 117 | 118 | found2 = YES; 119 | s2 = offset; 120 | offset += sepLen; 121 | 122 | HTTPLogVerbose(@"%@[%p]: Found s2 at %lu", THIS_FILE, self, (unsigned long)s2); 123 | } 124 | 125 | if (found1 && found2) 126 | { 127 | // We found our separators. 128 | // Now extract the string between the two separators. 129 | 130 | NSRange fullRange = NSMakeRange(s1, (s2 - s1 + sepLen)); 131 | NSRange strRange = NSMakeRange(s1 + sepLen, (s2 - s1 - sepLen)); 132 | 133 | // Wish we could use the simple subdataWithRange method. 134 | // But that method copies the bytes... 135 | // So for performance reasons, we need to use the methods that don't copy the bytes. 136 | 137 | void *strBuf = readBuffer + strRange.location; 138 | NSUInteger strLen = strRange.length; 139 | 140 | NSString *key = [[NSString alloc] initWithBytes:strBuf length:strLen encoding:NSUTF8StringEncoding]; 141 | if (key) 142 | { 143 | // Is there a given replacement for this key? 144 | 145 | id value = [replacementDict objectForKey:key]; 146 | if (value) 147 | { 148 | // Found the replacement value. 149 | // Now perform the replacement in the buffer. 150 | 151 | HTTPLogVerbose(@"%@[%p]: key(%@) -> value(%@)", THIS_FILE, self, key, value); 152 | 153 | NSData *v = [[value description] dataUsingEncoding:NSUTF8StringEncoding]; 154 | NSUInteger vLength = [v length]; 155 | 156 | if (fullRange.length == vLength) 157 | { 158 | // Replacement is exactly the same size as what it is replacing 159 | 160 | // memcpy(void *restrict dst, const void *restrict src, size_t n); 161 | 162 | memcpy(readBuffer + fullRange.location, [v bytes], vLength); 163 | } 164 | else // (fullRange.length != vLength) 165 | { 166 | NSInteger diff = (NSInteger)vLength - (NSInteger)fullRange.length; 167 | 168 | if (diff > 0) 169 | { 170 | // Replacement is bigger than what it is replacing. 171 | // Make sure there is room in the buffer for the replacement. 172 | 173 | if (diff > (readBufferSize - bufLen)) 174 | { 175 | NSUInteger inc = MAX(diff, 256); 176 | 177 | readBufferSize += inc; 178 | readBuffer = reallocf(readBuffer, readBufferSize); 179 | } 180 | } 181 | 182 | // Move the data that comes after the replacement. 183 | // 184 | // If replacement is smaller than what it is replacing, 185 | // then we are shifting the data toward the beginning of the buffer. 186 | // 187 | // If replacement is bigger than what it is replacing, 188 | // then we are shifting the data toward the end of the buffer. 189 | // 190 | // memmove(void *dst, const void *src, size_t n); 191 | // 192 | // The memmove() function copies n bytes from src to dst. 193 | // The two areas may overlap; the copy is always done in a non-destructive manner. 194 | 195 | void *src = readBuffer + fullRange.location + fullRange.length; 196 | void *dst = readBuffer + fullRange.location + vLength; 197 | 198 | NSUInteger remaining = bufLen - (fullRange.location + fullRange.length); 199 | 200 | memmove(dst, src, remaining); 201 | 202 | // Now copy the replacement into its location. 203 | // 204 | // memcpy(void *restrict dst, const void *restrict src, size_t n) 205 | // 206 | // The memcpy() function copies n bytes from src to dst. 207 | // If the two areas overlap, behavior is undefined. 208 | 209 | memcpy(readBuffer + fullRange.location, [v bytes], vLength); 210 | 211 | // And don't forget to update our indices. 212 | 213 | bufLen += diff; 214 | offset += diff; 215 | stopOffset += diff; 216 | } 217 | } 218 | 219 | } 220 | 221 | found1 = found2 = NO; 222 | } 223 | } 224 | else 225 | { 226 | offset++; 227 | } 228 | } 229 | 230 | // We've gone through our buffer now, and performed all the replacements that we could. 231 | // It's now time to update the amount of available data we have. 232 | 233 | if (readOffset == fileLength) 234 | { 235 | // We've read in the entire file. 236 | // So there can be no more replacements. 237 | 238 | data = [[NSData alloc] initWithBytes:readBuffer length:bufLen]; 239 | readBufferOffset = 0; 240 | } 241 | else 242 | { 243 | // There are a couple different situations that we need to take into account here. 244 | // 245 | // Imagine the following file: 246 | // My name is %%USER_NAME%% 247 | // 248 | // Situation 1: 249 | // The first chunk of data we read was "My name is %%". 250 | // So we found the first separator, but not the second. 251 | // In this case we can only return the data that precedes the first separator. 252 | // 253 | // Situation 2: 254 | // The first chunk of data we read was "My name is %". 255 | // So we didn't find any separators, but part of a separator may be included in our buffer. 256 | 257 | NSUInteger available; 258 | if (found1) 259 | { 260 | // Situation 1 261 | available = s1; 262 | } 263 | else 264 | { 265 | // Situation 2 266 | available = stopOffset; 267 | } 268 | 269 | // Copy available data 270 | 271 | data = [[NSData alloc] initWithBytes:readBuffer length:available]; 272 | 273 | // Remove the copied data from the buffer. 274 | // We do this by shifting the remaining data toward the beginning of the buffer. 275 | 276 | NSUInteger remaining = bufLen - available; 277 | 278 | memmove(readBuffer, readBuffer + available, remaining); 279 | readBufferOffset = remaining; 280 | } 281 | 282 | [connection responseHasAvailableData:self]; 283 | } 284 | 285 | - (void)dealloc 286 | { 287 | HTTPLogTrace(); 288 | 289 | 290 | } 291 | 292 | @end 293 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Responses/HTTPErrorResponse.h: -------------------------------------------------------------------------------- 1 | #import "HTTPResponse.h" 2 | 3 | @interface HTTPErrorResponse : NSObject { 4 | NSInteger _status; 5 | } 6 | 7 | - (id)initWithErrorCode:(int)httpErrorCode; 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Responses/HTTPErrorResponse.m: -------------------------------------------------------------------------------- 1 | #import "HTTPErrorResponse.h" 2 | 3 | @implementation HTTPErrorResponse 4 | 5 | -(id)initWithErrorCode:(int)httpErrorCode 6 | { 7 | if ((self = [super init])) 8 | { 9 | _status = httpErrorCode; 10 | } 11 | 12 | return self; 13 | } 14 | 15 | - (UInt64) contentLength { 16 | return 0; 17 | } 18 | 19 | - (UInt64) offset { 20 | return 0; 21 | } 22 | 23 | - (void)setOffset:(UInt64)offset { 24 | ; 25 | } 26 | 27 | - (NSData*) readDataOfLength:(NSUInteger)length { 28 | return nil; 29 | } 30 | 31 | - (BOOL) isDone { 32 | return YES; 33 | } 34 | 35 | - (NSInteger) status { 36 | return _status; 37 | } 38 | @end 39 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Responses/HTTPFileResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPResponse.h" 3 | 4 | @class HTTPConnection; 5 | 6 | 7 | @interface HTTPFileResponse : NSObject 8 | { 9 | HTTPConnection *connection; 10 | 11 | NSString *filePath; 12 | UInt64 fileLength; 13 | UInt64 fileOffset; 14 | 15 | BOOL aborted; 16 | 17 | int fileFD; 18 | void *buffer; 19 | NSUInteger bufferSize; 20 | } 21 | 22 | - (id)initWithFilePath:(NSString *)filePath forConnection:(HTTPConnection *)connection; 23 | - (NSString *)filePath; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Responses/HTTPFileResponse.m: -------------------------------------------------------------------------------- 1 | #import "HTTPFileResponse.h" 2 | #import "HTTPConnection.h" 3 | #import "HTTPLogging.h" 4 | 5 | #import 6 | #import 7 | 8 | #if ! __has_feature(objc_arc) 9 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 10 | #endif 11 | 12 | // Log levels : off, error, warn, info, verbose 13 | // Other flags: trace 14 | static const int httpLogLevel = HTTP_LOG_LEVEL_WARN; // | HTTP_LOG_FLAG_TRACE; 15 | 16 | #define NULL_FD -1 17 | 18 | 19 | @implementation HTTPFileResponse 20 | 21 | - (id)initWithFilePath:(NSString *)fpath forConnection:(HTTPConnection *)parent 22 | { 23 | if((self = [super init])) 24 | { 25 | HTTPLogTrace(); 26 | 27 | connection = parent; // Parents retain children, children do NOT retain parents 28 | 29 | fileFD = NULL_FD; 30 | filePath = [[fpath copy] stringByResolvingSymlinksInPath]; 31 | if (filePath == nil) 32 | { 33 | HTTPLogWarn(@"%@: Init failed - Nil filePath", THIS_FILE); 34 | 35 | return nil; 36 | } 37 | 38 | NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil]; 39 | if (fileAttributes == nil) 40 | { 41 | HTTPLogWarn(@"%@: Init failed - Unable to get file attributes. filePath: %@", THIS_FILE, filePath); 42 | 43 | return nil; 44 | } 45 | 46 | fileLength = (UInt64)[[fileAttributes objectForKey:NSFileSize] unsignedLongLongValue]; 47 | fileOffset = 0; 48 | 49 | aborted = NO; 50 | 51 | // We don't bother opening the file here. 52 | // If this is a HEAD request we only need to know the fileLength. 53 | } 54 | return self; 55 | } 56 | 57 | - (void)abort 58 | { 59 | HTTPLogTrace(); 60 | 61 | [connection responseDidAbort:self]; 62 | aborted = YES; 63 | } 64 | 65 | - (BOOL)openFile 66 | { 67 | HTTPLogTrace(); 68 | 69 | fileFD = open([filePath UTF8String], O_RDONLY); 70 | if (fileFD == NULL_FD) 71 | { 72 | HTTPLogError(@"%@[%p]: Unable to open file. filePath: %@", THIS_FILE, self, filePath); 73 | 74 | [self abort]; 75 | return NO; 76 | } 77 | 78 | HTTPLogVerbose(@"%@[%p]: Open fd[%i] -> %@", THIS_FILE, self, fileFD, filePath); 79 | 80 | return YES; 81 | } 82 | 83 | - (BOOL)openFileIfNeeded 84 | { 85 | if (aborted) 86 | { 87 | // The file operation has been aborted. 88 | // This could be because we failed to open the file, 89 | // or the reading process failed. 90 | return NO; 91 | } 92 | 93 | if (fileFD != NULL_FD) 94 | { 95 | // File has already been opened. 96 | return YES; 97 | } 98 | 99 | return [self openFile]; 100 | } 101 | 102 | - (UInt64)contentLength 103 | { 104 | HTTPLogTrace(); 105 | 106 | return fileLength; 107 | } 108 | 109 | - (UInt64)offset 110 | { 111 | HTTPLogTrace(); 112 | 113 | return fileOffset; 114 | } 115 | 116 | - (void)setOffset:(UInt64)offset 117 | { 118 | HTTPLogTrace2(@"%@[%p]: setOffset:%llu", THIS_FILE, self, offset); 119 | 120 | if (![self openFileIfNeeded]) 121 | { 122 | // File opening failed, 123 | // or response has been aborted due to another error. 124 | return; 125 | } 126 | 127 | fileOffset = offset; 128 | 129 | off_t result = lseek(fileFD, (off_t)offset, SEEK_SET); 130 | if (result == -1) 131 | { 132 | HTTPLogError(@"%@[%p]: lseek failed - errno(%i) filePath(%@)", THIS_FILE, self, errno, filePath); 133 | 134 | [self abort]; 135 | } 136 | } 137 | 138 | - (NSData *)readDataOfLength:(NSUInteger)length 139 | { 140 | HTTPLogTrace2(@"%@[%p]: readDataOfLength:%lu", THIS_FILE, self, (unsigned long)length); 141 | 142 | if (![self openFileIfNeeded]) 143 | { 144 | // File opening failed, 145 | // or response has been aborted due to another error. 146 | return nil; 147 | } 148 | 149 | // Determine how much data we should read. 150 | // 151 | // It is OK if we ask to read more bytes than exist in the file. 152 | // It is NOT OK to over-allocate the buffer. 153 | 154 | UInt64 bytesLeftInFile = fileLength - fileOffset; 155 | 156 | NSUInteger bytesToRead = (NSUInteger)MIN(length, bytesLeftInFile); 157 | 158 | // Make sure buffer is big enough for read request. 159 | // Do not over-allocate. 160 | 161 | if (buffer == NULL || bufferSize < bytesToRead) 162 | { 163 | bufferSize = bytesToRead; 164 | buffer = reallocf(buffer, (size_t)bufferSize); 165 | 166 | if (buffer == NULL) 167 | { 168 | HTTPLogError(@"%@[%p]: Unable to allocate buffer", THIS_FILE, self); 169 | 170 | [self abort]; 171 | return nil; 172 | } 173 | } 174 | 175 | // Perform the read 176 | 177 | HTTPLogVerbose(@"%@[%p]: Attempting to read %lu bytes from file", THIS_FILE, self, (unsigned long)bytesToRead); 178 | 179 | ssize_t result = read(fileFD, buffer, bytesToRead); 180 | 181 | // Check the results 182 | 183 | if (result < 0) 184 | { 185 | HTTPLogError(@"%@: Error(%i) reading file(%@)", THIS_FILE, errno, filePath); 186 | 187 | [self abort]; 188 | return nil; 189 | } 190 | else if (result == 0) 191 | { 192 | HTTPLogError(@"%@: Read EOF on file(%@)", THIS_FILE, filePath); 193 | 194 | [self abort]; 195 | return nil; 196 | } 197 | else // (result > 0) 198 | { 199 | HTTPLogVerbose(@"%@[%p]: Read %ld bytes from file", THIS_FILE, self, (long)result); 200 | 201 | fileOffset += result; 202 | 203 | return [NSData dataWithBytes:buffer length:result]; 204 | } 205 | } 206 | 207 | - (BOOL)isDone 208 | { 209 | BOOL result = (fileOffset == fileLength); 210 | 211 | HTTPLogTrace2(@"%@[%p]: isDone - %@", THIS_FILE, self, (result ? @"YES" : @"NO")); 212 | 213 | return result; 214 | } 215 | 216 | - (NSString *)filePath 217 | { 218 | return filePath; 219 | } 220 | 221 | - (void)dealloc 222 | { 223 | HTTPLogTrace(); 224 | 225 | if (fileFD != NULL_FD) 226 | { 227 | HTTPLogVerbose(@"%@[%p]: Close fd[%i]", THIS_FILE, self, fileFD); 228 | 229 | close(fileFD); 230 | } 231 | 232 | if (buffer) 233 | free(buffer); 234 | 235 | } 236 | 237 | @end 238 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Responses/HTTPRedirectResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPResponse.h" 3 | 4 | 5 | @interface HTTPRedirectResponse : NSObject 6 | { 7 | NSString *redirectPath; 8 | } 9 | 10 | - (id)initWithPath:(NSString *)redirectPath; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/Responses/HTTPRedirectResponse.m: -------------------------------------------------------------------------------- 1 | #import "HTTPRedirectResponse.h" 2 | #import "HTTPLogging.h" 3 | 4 | #if ! __has_feature(objc_arc) 5 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 6 | #endif 7 | 8 | // Log levels : off, error, warn, info, verbose 9 | // Other flags: trace 10 | static const int httpLogLevel = HTTP_LOG_LEVEL_OFF; // | HTTP_LOG_FLAG_TRACE; 11 | 12 | 13 | @implementation HTTPRedirectResponse 14 | 15 | - (id)initWithPath:(NSString *)path 16 | { 17 | if ((self = [super init])) 18 | { 19 | HTTPLogTrace(); 20 | 21 | redirectPath = [path copy]; 22 | } 23 | return self; 24 | } 25 | 26 | - (UInt64)contentLength 27 | { 28 | return 0; 29 | } 30 | 31 | - (UInt64)offset 32 | { 33 | return 0; 34 | } 35 | 36 | - (void)setOffset:(UInt64)offset 37 | { 38 | // Nothing to do 39 | } 40 | 41 | - (NSData *)readDataOfLength:(NSUInteger)length 42 | { 43 | HTTPLogTrace(); 44 | 45 | return nil; 46 | } 47 | 48 | - (BOOL)isDone 49 | { 50 | return YES; 51 | } 52 | 53 | - (NSDictionary *)httpHeaders 54 | { 55 | HTTPLogTrace(); 56 | 57 | return [NSDictionary dictionaryWithObject:redirectPath forKey:@"Location"]; 58 | } 59 | 60 | - (NSInteger)status 61 | { 62 | HTTPLogTrace(); 63 | 64 | return 302; 65 | } 66 | 67 | - (void)dealloc 68 | { 69 | HTTPLogTrace(); 70 | 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaHTTPServer/WebSocket.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class HTTPMessage; 4 | @class GCDAsyncSocket; 5 | 6 | 7 | #define WebSocketDidDieNotification @"WebSocketDidDie" 8 | 9 | @interface WebSocket : NSObject 10 | { 11 | dispatch_queue_t websocketQueue; 12 | 13 | HTTPMessage *request; 14 | GCDAsyncSocket *asyncSocket; 15 | 16 | NSData *term; 17 | 18 | BOOL isStarted; 19 | BOOL isOpen; 20 | BOOL isVersion76; 21 | 22 | id __unsafe_unretained delegate; 23 | } 24 | 25 | + (BOOL)isWebSocketRequest:(HTTPMessage *)request; 26 | 27 | - (id)initWithRequest:(HTTPMessage *)request socket:(GCDAsyncSocket *)socket; 28 | 29 | /** 30 | * Delegate option. 31 | * 32 | * In most cases it will be easier to subclass WebSocket, 33 | * but some circumstances may lead one to prefer standard delegate callbacks instead. 34 | **/ 35 | @property (/* atomic */ unsafe_unretained) id delegate; 36 | 37 | /** 38 | * The WebSocket class is thread-safe, generally via it's GCD queue. 39 | * All public API methods are thread-safe, 40 | * and the subclass API methods are thread-safe as they are all invoked on the same GCD queue. 41 | **/ 42 | @property (nonatomic, readonly) dispatch_queue_t websocketQueue; 43 | 44 | /** 45 | * Public API 46 | * 47 | * These methods are automatically called by the HTTPServer. 48 | * You may invoke the stop method yourself to close the WebSocket manually. 49 | **/ 50 | - (void)start; 51 | - (void)stop; 52 | 53 | /** 54 | * Public API 55 | * 56 | * Sends a message over the WebSocket. 57 | * This method is thread-safe. 58 | **/ 59 | - (void)sendMessage:(NSString *)msg; 60 | 61 | /** 62 | * Public API 63 | * 64 | * Sends a message over the WebSocket. 65 | * This method is thread-safe. 66 | **/ 67 | - (void)sendData:(NSData *)msg; 68 | 69 | /** 70 | * Subclass API 71 | * 72 | * These methods are designed to be overriden by subclasses. 73 | **/ 74 | - (void)didOpen; 75 | - (void)didReceiveMessage:(NSString *)msg; 76 | - (void)didClose; 77 | 78 | @end 79 | 80 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | #pragma mark - 82 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 83 | 84 | /** 85 | * There are two ways to create your own custom WebSocket: 86 | * 87 | * - Subclass it and override the methods you're interested in. 88 | * - Use traditional delegate paradigm along with your own custom class. 89 | * 90 | * They both exist to allow for maximum flexibility. 91 | * In most cases it will be easier to subclass WebSocket. 92 | * However some circumstances may lead one to prefer standard delegate callbacks instead. 93 | * One such example, you're already subclassing another class, so subclassing WebSocket isn't an option. 94 | **/ 95 | 96 | @protocol WebSocketDelegate 97 | @optional 98 | 99 | - (void)webSocketDidOpen:(WebSocket *)ws; 100 | 101 | - (void)webSocket:(WebSocket *)ws didReceiveMessage:(NSString *)msg; 102 | 103 | - (void)webSocketDidClose:(WebSocket *)ws; 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/DDASLLogger.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import "DDLog.h" 5 | 6 | /** 7 | * Welcome to Cocoa Lumberjack! 8 | * 9 | * The project page has a wealth of documentation if you have any questions. 10 | * https://github.com/CocoaLumberjack/CocoaLumberjack 11 | * 12 | * If you're new to the project you may wish to read the "Getting Started" wiki. 13 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted 14 | * 15 | * 16 | * This class provides a logger for the Apple System Log facility. 17 | * 18 | * As described in the "Getting Started" page, 19 | * the traditional NSLog() function directs it's output to two places: 20 | * 21 | * - Apple System Log 22 | * - StdErr (if stderr is a TTY) so log statements show up in Xcode console 23 | * 24 | * To duplicate NSLog() functionality you can simply add this logger and a tty logger. 25 | * However, if you instead choose to use file logging (for faster performance), 26 | * you may choose to use a file logger and a tty logger. 27 | **/ 28 | 29 | @interface DDASLLogger : DDAbstractLogger 30 | { 31 | aslclient client; 32 | } 33 | 34 | + (instancetype)sharedInstance; 35 | 36 | // Inherited from DDAbstractLogger 37 | 38 | // - (id )logFormatter; 39 | // - (void)setLogFormatter:(id )formatter; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/DDASLLogger.m: -------------------------------------------------------------------------------- 1 | #import "DDASLLogger.h" 2 | 3 | #import 4 | 5 | /** 6 | * Welcome to Cocoa Lumberjack! 7 | * 8 | * The project page has a wealth of documentation if you have any questions. 9 | * https://github.com/CocoaLumberjack/CocoaLumberjack 10 | * 11 | * If you're new to the project you may wish to read the "Getting Started" wiki. 12 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted 13 | **/ 14 | 15 | #if ! __has_feature(objc_arc) 16 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 17 | #endif 18 | 19 | 20 | @implementation DDASLLogger 21 | 22 | static DDASLLogger *sharedInstance; 23 | 24 | /** 25 | * The runtime sends initialize to each class in a program exactly one time just before the class, 26 | * or any class that inherits from it, is sent its first message from within the program. (Thus the 27 | * method may never be invoked if the class is not used.) The runtime sends the initialize message to 28 | * classes in a thread-safe manner. Superclasses receive this message before their subclasses. 29 | * 30 | * This method may also be called directly (assumably by accident), hence the safety mechanism. 31 | **/ 32 | + (void)initialize 33 | { 34 | static BOOL initialized = NO; 35 | if (!initialized) 36 | { 37 | initialized = YES; 38 | 39 | sharedInstance = [[[self class] alloc] init]; 40 | } 41 | } 42 | 43 | + (instancetype)sharedInstance 44 | { 45 | return sharedInstance; 46 | } 47 | 48 | - (id)init 49 | { 50 | if (sharedInstance != nil) 51 | { 52 | return nil; 53 | } 54 | 55 | if ((self = [super init])) 56 | { 57 | // A default asl client is provided for the main thread, 58 | // but background threads need to create their own client. 59 | 60 | client = asl_open(NULL, "com.apple.console", 0); 61 | } 62 | return self; 63 | } 64 | 65 | - (void)logMessage:(DDLogMessage *)logMessage 66 | { 67 | NSString *logMsg = logMessage->logMsg; 68 | 69 | if (formatter) 70 | { 71 | logMsg = [formatter formatLogMessage:logMessage]; 72 | } 73 | 74 | if (logMsg) 75 | { 76 | const char *msg = [logMsg UTF8String]; 77 | 78 | int aslLogLevel; 79 | switch (logMessage->logFlag) 80 | { 81 | // Note: By default ASL will filter anything above level 5 (Notice). 82 | // So our mappings shouldn't go above that level. 83 | 84 | case LOG_FLAG_ERROR : aslLogLevel = ASL_LEVEL_ALERT; break; 85 | case LOG_FLAG_WARN : aslLogLevel = ASL_LEVEL_CRIT; break; 86 | case LOG_FLAG_INFO : aslLogLevel = ASL_LEVEL_ERR; break; 87 | case LOG_FLAG_DEBUG : aslLogLevel = ASL_LEVEL_WARNING; break; 88 | default : aslLogLevel = ASL_LEVEL_NOTICE; break; 89 | } 90 | 91 | asl_log(client, NULL, aslLogLevel, "%s", msg); 92 | } 93 | } 94 | 95 | - (NSString *)loggerName 96 | { 97 | return @"cocoa.lumberjack.aslLogger"; 98 | } 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/DDAbstractDatabaseLogger.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "DDLog.h" 4 | 5 | /** 6 | * Welcome to Cocoa Lumberjack! 7 | * 8 | * The project page has a wealth of documentation if you have any questions. 9 | * https://github.com/CocoaLumberjack/CocoaLumberjack 10 | * 11 | * If you're new to the project you may wish to read the "Getting Started" wiki. 12 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted 13 | * 14 | * 15 | * This class provides an abstract implementation of a database logger. 16 | * 17 | * That is, it provides the base implementation for a database logger to build atop of. 18 | * All that is needed for a concrete database logger is to extend this class 19 | * and override the methods in the implementation file that are prefixed with "db_". 20 | **/ 21 | 22 | @interface DDAbstractDatabaseLogger : DDAbstractLogger { 23 | @protected 24 | NSUInteger saveThreshold; 25 | NSTimeInterval saveInterval; 26 | NSTimeInterval maxAge; 27 | NSTimeInterval deleteInterval; 28 | BOOL deleteOnEverySave; 29 | 30 | BOOL saveTimerSuspended; 31 | NSUInteger unsavedCount; 32 | dispatch_time_t unsavedTime; 33 | dispatch_source_t saveTimer; 34 | dispatch_time_t lastDeleteTime; 35 | dispatch_source_t deleteTimer; 36 | } 37 | 38 | /** 39 | * Specifies how often to save the data to disk. 40 | * Since saving is an expensive operation (disk io) it is not done after every log statement. 41 | * These properties allow you to configure how/when the logger saves to disk. 42 | * 43 | * A save is done when either (whichever happens first): 44 | * 45 | * - The number of unsaved log entries reaches saveThreshold 46 | * - The amount of time since the oldest unsaved log entry was created reaches saveInterval 47 | * 48 | * You can optionally disable the saveThreshold by setting it to zero. 49 | * If you disable the saveThreshold you are entirely dependent on the saveInterval. 50 | * 51 | * You can optionally disable the saveInterval by setting it to zero (or a negative value). 52 | * If you disable the saveInterval you are entirely dependent on the saveThreshold. 53 | * 54 | * It's not wise to disable both saveThreshold and saveInterval. 55 | * 56 | * The default saveThreshold is 500. 57 | * The default saveInterval is 60 seconds. 58 | **/ 59 | @property (assign, readwrite) NSUInteger saveThreshold; 60 | @property (assign, readwrite) NSTimeInterval saveInterval; 61 | 62 | /** 63 | * It is likely you don't want the log entries to persist forever. 64 | * Doing so would allow the database to grow infinitely large over time. 65 | * 66 | * The maxAge property provides a way to specify how old a log statement can get 67 | * before it should get deleted from the database. 68 | * 69 | * The deleteInterval specifies how often to sweep for old log entries. 70 | * Since deleting is an expensive operation (disk io) is is done on a fixed interval. 71 | * 72 | * An alternative to the deleteInterval is the deleteOnEverySave option. 73 | * This specifies that old log entries should be deleted during every save operation. 74 | * 75 | * You can optionally disable the maxAge by setting it to zero (or a negative value). 76 | * If you disable the maxAge then old log statements are not deleted. 77 | * 78 | * You can optionally disable the deleteInterval by setting it to zero (or a negative value). 79 | * 80 | * If you disable both deleteInterval and deleteOnEverySave then old log statements are not deleted. 81 | * 82 | * It's not wise to enable both deleteInterval and deleteOnEverySave. 83 | * 84 | * The default maxAge is 7 days. 85 | * The default deleteInterval is 5 minutes. 86 | * The default deleteOnEverySave is NO. 87 | **/ 88 | @property (assign, readwrite) NSTimeInterval maxAge; 89 | @property (assign, readwrite) NSTimeInterval deleteInterval; 90 | @property (assign, readwrite) BOOL deleteOnEverySave; 91 | 92 | /** 93 | * Forces a save of any pending log entries (flushes log entries to disk). 94 | **/ 95 | - (void)savePendingLogEntries; 96 | 97 | /** 98 | * Removes any log entries that are older than maxAge. 99 | **/ 100 | - (void)deleteOldLogEntries; 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/DDLog+LOGV.h: -------------------------------------------------------------------------------- 1 | // 2 | // DDLog+LOGV.h 3 | // Lumberjack 4 | // 5 | // Created by Mike Pontillo on 11/20/12. 6 | // 7 | // 8 | 9 | #ifndef Lumberjack_DDLog_LOGV_h 10 | #define Lumberjack_DDLog_LOGV_h 11 | 12 | #import "DDLog.h" 13 | 14 | 15 | #define LOGV_MACRO(isAsynchronous, lvl, flg, ctx, atag, fnct, frmt, avalist) \ 16 | [DDLog log:isAsynchronous \ 17 | level:lvl \ 18 | flag:flg \ 19 | context:ctx \ 20 | file:__FILE__ \ 21 | function:fnct \ 22 | line:__LINE__ \ 23 | tag:atag \ 24 | format:frmt \ 25 | args:avalist] 26 | 27 | #define LOGV_OBJC_MACRO(async, lvl, flg, ctx, frmt, avalist) \ 28 | LOGV_MACRO(async, lvl, flg, ctx, nil, sel_getName(_cmd), frmt, avalist) 29 | 30 | #define LOGV_C_MACRO(async, lvl, flg, ctx, frmt, avalist) \ 31 | LOGV_MACRO(async, lvl, flg, ctx, nil, __FUNCTION__, frmt, avalist) 32 | 33 | 34 | 35 | #define SYNC_LOGV_OBJC_MACRO(lvl, flg, ctx, frmt, avalist) \ 36 | LOGV_OBJC_MACRO( NO, lvl, flg, ctx, frmt, avalist) 37 | 38 | #define ASYNC_LOGV_OBJC_MACRO(lvl, flg, ctx, frmt, avalist) \ 39 | LOGV_OBJC_MACRO(YES, lvl, flg, ctx, frmt, avalist) 40 | 41 | #define SYNC_LOGV_C_MACRO(lvl, flg, ctx, frmt, avalist) \ 42 | LOGV_C_MACRO( NO, lvl, flg, ctx, frmt, avalist) 43 | 44 | #define ASYNC_LOGV_C_MACRO(lvl, flg, ctx, frmt, avalist) \ 45 | LOGV_C_MACRO(YES, lvl, flg, ctx, frmt, avalist) 46 | 47 | 48 | 49 | #define LOGV_MAYBE(async, lvl, flg, ctx, fnct, frmt, avalist) \ 50 | do { if(lvl & flg) LOGV_MACRO(async, lvl, flg, ctx, nil, fnct, frmt, avalist); } while(0) 51 | 52 | #define LOGV_OBJC_MAYBE(async, lvl, flg, ctx, frmt, avalist) \ 53 | LOGV_MAYBE(async, lvl, flg, ctx, sel_getName(_cmd), frmt, avalist) 54 | 55 | #define LOGV_C_MAYBE(async, lvl, flg, ctx, frmt, avalist) \ 56 | LOGV_MAYBE(async, lvl, flg, ctx, __FUNCTION__, frmt, avalist) 57 | 58 | #define SYNC_LOGV_OBJC_MAYBE(lvl, flg, ctx, frmt, avalist) \ 59 | LOGV_OBJC_MAYBE( NO, lvl, flg, ctx, frmt, avalist) 60 | 61 | #define ASYNC_LOGV_OBJC_MAYBE(lvl, flg, ctx, frmt, avalist) \ 62 | LOGV_OBJC_MAYBE(YES, lvl, flg, ctx, frmt, avalist) 63 | 64 | #define SYNC_LOGV_C_MAYBE(lvl, flg, ctx, frmt, avalist) \ 65 | LOGV_C_MAYBE( NO, lvl, flg, ctx, frmt, avalist) 66 | 67 | #define ASYNC_LOGV_C_MAYBE(lvl, flg, ctx, frmt, avalist) \ 68 | LOGV_C_MAYBE(YES, lvl, flg, ctx, frmt, avalist) 69 | 70 | 71 | 72 | #define LOGV_OBJC_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, avalist) \ 73 | LOGV_MACRO(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, avalist) 74 | 75 | #define LOGV_C_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, avalist) \ 76 | LOGV_MACRO(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, avalist) 77 | 78 | #define LOGV_TAG_MAYBE(async, lvl, flg, ctx, tag, fnct, frmt, avalist) \ 79 | do { if(lvl & flg) LOGV_MACRO(async, lvl, flg, ctx, tag, fnct, frmt, avalist); } while(0) 80 | 81 | #define LOGV_OBJC_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, avalist) \ 82 | LOGV_TAG_MAYBE(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, avalist) 83 | 84 | #define LOGV_C_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, avalist) \ 85 | LOGV_TAG_MAYBE(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, avalist) 86 | 87 | 88 | 89 | #define DDLogvError(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_ERROR, ddLogLevel, LOG_FLAG_ERROR, 0, frmt, avalist) 90 | #define DDLogvWarn(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_WARN, ddLogLevel, LOG_FLAG_WARN, 0, frmt, avalist) 91 | #define DDLogvInfo(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_INFO, ddLogLevel, LOG_FLAG_INFO, 0, frmt, avalist) 92 | #define DDLogvVerbose(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_VERBOSE, ddLogLevel, LOG_FLAG_VERBOSE, 0, frmt, avalist) 93 | 94 | #define DDLogvCError(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_ERROR, ddLogLevel, LOG_FLAG_ERROR, 0, frmt, avalist) 95 | #define DDLogvCWarn(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_WARN, ddLogLevel, LOG_FLAG_WARN, 0, frmt, avalist) 96 | #define DDLogvCInfo(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_INFO, ddLogLevel, LOG_FLAG_INFO, 0, frmt, avalist) 97 | #define DDLogvCVerbose(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_VERBOSE, ddLogLevel, LOG_FLAG_VERBOSE, 0, frmt, avalist) 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/DDTTYLogger.h: -------------------------------------------------------------------------------- 1 | #import 2 | #if TARGET_OS_IPHONE 3 | #import 4 | #else 5 | #import 6 | #endif 7 | 8 | #import "DDLog.h" 9 | 10 | #define LOG_CONTEXT_ALL INT_MAX 11 | 12 | /** 13 | * Welcome to Cocoa Lumberjack! 14 | * 15 | * The project page has a wealth of documentation if you have any questions. 16 | * https://github.com/CocoaLumberjack/CocoaLumberjack 17 | * 18 | * If you're new to the project you may wish to read the "Getting Started" wiki. 19 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted 20 | * 21 | * 22 | * This class provides a logger for Terminal output or Xcode console output, 23 | * depending on where you are running your code. 24 | * 25 | * As described in the "Getting Started" page, 26 | * the traditional NSLog() function directs it's output to two places: 27 | * 28 | * - Apple System Log (so it shows up in Console.app) 29 | * - StdErr (if stderr is a TTY, so log statements show up in Xcode console) 30 | * 31 | * To duplicate NSLog() functionality you can simply add this logger and an asl logger. 32 | * However, if you instead choose to use file logging (for faster performance), 33 | * you may choose to use only a file logger and a tty logger. 34 | **/ 35 | 36 | @interface DDTTYLogger : DDAbstractLogger 37 | { 38 | NSCalendar *calendar; 39 | NSUInteger calendarUnitFlags; 40 | 41 | NSString *appName; 42 | char *app; 43 | size_t appLen; 44 | 45 | NSString *processID; 46 | char *pid; 47 | size_t pidLen; 48 | 49 | BOOL colorsEnabled; 50 | NSMutableArray *colorProfilesArray; 51 | NSMutableDictionary *colorProfilesDict; 52 | } 53 | 54 | + (instancetype)sharedInstance; 55 | 56 | /* Inherited from the DDLogger protocol: 57 | * 58 | * Formatters may optionally be added to any logger. 59 | * 60 | * If no formatter is set, the logger simply logs the message as it is given in logMessage, 61 | * or it may use its own built in formatting style. 62 | * 63 | * More information about formatters can be found here: 64 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomFormatters 65 | * 66 | * The actual implementation of these methods is inherited from DDAbstractLogger. 67 | 68 | - (id )logFormatter; 69 | - (void)setLogFormatter:(id )formatter; 70 | 71 | */ 72 | 73 | /** 74 | * Want to use different colors for different log levels? 75 | * Enable this property. 76 | * 77 | * If you run the application via the Terminal (not Xcode), 78 | * the logger will map colors to xterm-256color or xterm-color (if available). 79 | * 80 | * Xcode does NOT natively support colors in the Xcode debugging console. 81 | * You'll need to install the XcodeColors plugin to see colors in the Xcode console. 82 | * https://github.com/robbiehanson/XcodeColors 83 | * 84 | * The default value if NO. 85 | **/ 86 | @property (readwrite, assign) BOOL colorsEnabled; 87 | 88 | /** 89 | * The default color set (foregroundColor, backgroundColor) is: 90 | * 91 | * - LOG_FLAG_ERROR = (red, nil) 92 | * - LOG_FLAG_WARN = (orange, nil) 93 | * 94 | * You can customize the colors however you see fit. 95 | * Please note that you are passing a flag, NOT a level. 96 | * 97 | * GOOD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:LOG_FLAG_INFO]; // <- Good :) 98 | * BAD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:LOG_LEVEL_INFO]; // <- BAD! :( 99 | * 100 | * LOG_FLAG_INFO = 0...00100 101 | * LOG_LEVEL_INFO = 0...00111 <- Would match LOG_FLAG_INFO and LOG_FLAG_WARN and LOG_FLAG_ERROR 102 | * 103 | * If you run the application within Xcode, then the XcodeColors plugin is required. 104 | * 105 | * If you run the application from a shell, then DDTTYLogger will automatically map the given color to 106 | * the closest available color. (xterm-256color or xterm-color which have 256 and 16 supported colors respectively.) 107 | * 108 | * This method invokes setForegroundColor:backgroundColor:forFlag:context: and applies it to `LOG_CONTEXT_ALL`. 109 | **/ 110 | #if TARGET_OS_IPHONE 111 | - (void)setForegroundColor:(UIColor *)txtColor backgroundColor:(UIColor *)bgColor forFlag:(int)mask; 112 | #else 113 | - (void)setForegroundColor:(NSColor *)txtColor backgroundColor:(NSColor *)bgColor forFlag:(int)mask; 114 | #endif 115 | 116 | /** 117 | * Just like setForegroundColor:backgroundColor:flag, but allows you to specify a particular logging context. 118 | * 119 | * A logging context is often used to identify log messages coming from a 3rd party framework, 120 | * although logging context's can be used for many different functions. 121 | * 122 | * Use LOG_CONTEXT_ALL to set the deafult color for all contexts that have no specific color set defined. 123 | * 124 | * Logging context's are explained in further detail here: 125 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomContext 126 | **/ 127 | #if TARGET_OS_IPHONE 128 | - (void)setForegroundColor:(UIColor *)txtColor backgroundColor:(UIColor *)bgColor forFlag:(int)mask context:(int)ctxt; 129 | #else 130 | - (void)setForegroundColor:(NSColor *)txtColor backgroundColor:(NSColor *)bgColor forFlag:(int)mask context:(int)ctxt; 131 | #endif 132 | 133 | /** 134 | * Similar to the methods above, but allows you to map DDLogMessage->tag to a particular color profile. 135 | * For example, you could do something like this: 136 | * 137 | * static NSString *const PurpleTag = @"PurpleTag"; 138 | * 139 | * #define DDLogPurple(frmt, ...) LOG_OBJC_TAG_MACRO(NO, 0, 0, 0, PurpleTag, frmt, ##__VA_ARGS__) 140 | * 141 | * And then in your applicationDidFinishLaunching, or wherever you configure Lumberjack: 142 | * 143 | * #if TARGET_OS_IPHONE 144 | * UIColor *purple = [UIColor colorWithRed:(64/255.0) green:(0/255.0) blue:(128/255.0) alpha:1.0]; 145 | * #else 146 | * NSColor *purple = [NSColor colorWithCalibratedRed:(64/255.0) green:(0/255.0) blue:(128/255.0) alpha:1.0]; 147 | * 148 | * [[DDTTYLogger sharedInstance] setForegroundColor:purple backgroundColor:nil forTag:PurpleTag]; 149 | * [DDLog addLogger:[DDTTYLogger sharedInstance]]; 150 | * 151 | * This would essentially give you a straight NSLog replacement that prints in purple: 152 | * 153 | * DDLogPurple(@"I'm a purple log message!"); 154 | **/ 155 | #if TARGET_OS_IPHONE 156 | - (void)setForegroundColor:(UIColor *)txtColor backgroundColor:(UIColor *)bgColor forTag:(id )tag; 157 | #else 158 | - (void)setForegroundColor:(NSColor *)txtColor backgroundColor:(NSColor *)bgColor forTag:(id )tag; 159 | #endif 160 | 161 | /** 162 | * Clearing color profiles. 163 | **/ 164 | - (void)clearColorsForFlag:(int)mask; 165 | - (void)clearColorsForFlag:(int)mask context:(int)context; 166 | - (void)clearColorsForTag:(id )tag; 167 | - (void)clearColorsForAllFlags; 168 | - (void)clearColorsForAllTags; 169 | - (void)clearAllColors; 170 | 171 | @end 172 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/Extensions/DDContextFilterLogFormatter.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "DDLog.h" 3 | 4 | /** 5 | * Welcome to Cocoa Lumberjack! 6 | * 7 | * The project page has a wealth of documentation if you have any questions. 8 | * https://github.com/CocoaLumberjack/CocoaLumberjack 9 | * 10 | * If you're new to the project you may wish to read the "Getting Started" page. 11 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted 12 | * 13 | * 14 | * This class provides a log formatter that filters log statements from a logging context not on the whitelist. 15 | * 16 | * A log formatter can be added to any logger to format and/or filter its output. 17 | * You can learn more about log formatters here: 18 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomFormatters 19 | * 20 | * You can learn more about logging context's here: 21 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomContext 22 | * 23 | * But here's a quick overview / refresher: 24 | * 25 | * Every log statement has a logging context. 26 | * These come from the underlying logging macros defined in DDLog.h. 27 | * The default logging context is zero. 28 | * You can define multiple logging context's for use in your application. 29 | * For example, logically separate parts of your app each have a different logging context. 30 | * Also 3rd party frameworks that make use of Lumberjack generally use their own dedicated logging context. 31 | **/ 32 | @interface DDContextWhitelistFilterLogFormatter : NSObject 33 | 34 | - (id)init; 35 | 36 | - (void)addToWhitelist:(int)loggingContext; 37 | - (void)removeFromWhitelist:(int)loggingContext; 38 | 39 | - (NSArray *)whitelist; 40 | 41 | - (BOOL)isOnWhitelist:(int)loggingContext; 42 | 43 | @end 44 | 45 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 46 | #pragma mark - 47 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | 49 | /** 50 | * This class provides a log formatter that filters log statements from a logging context on the blacklist. 51 | **/ 52 | @interface DDContextBlacklistFilterLogFormatter : NSObject 53 | 54 | - (id)init; 55 | 56 | - (void)addToBlacklist:(int)loggingContext; 57 | - (void)removeFromBlacklist:(int)loggingContext; 58 | 59 | - (NSArray *)blacklist; 60 | 61 | - (BOOL)isOnBlacklist:(int)loggingContext; 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/Extensions/DDContextFilterLogFormatter.m: -------------------------------------------------------------------------------- 1 | #import "DDContextFilterLogFormatter.h" 2 | #import 3 | 4 | /** 5 | * Welcome to Cocoa Lumberjack! 6 | * 7 | * The project page has a wealth of documentation if you have any questions. 8 | * https://github.com/CocoaLumberjack/CocoaLumberjack 9 | * 10 | * If you're new to the project you may wish to read the "Getting Started" wiki. 11 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted 12 | **/ 13 | 14 | #if ! __has_feature(objc_arc) 15 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 16 | #endif 17 | 18 | @interface DDLoggingContextSet : NSObject 19 | 20 | - (void)addToSet:(int)loggingContext; 21 | - (void)removeFromSet:(int)loggingContext; 22 | 23 | - (NSArray *)currentSet; 24 | 25 | - (BOOL)isInSet:(int)loggingContext; 26 | 27 | @end 28 | 29 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | #pragma mark - 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | @implementation DDContextWhitelistFilterLogFormatter 34 | { 35 | DDLoggingContextSet *contextSet; 36 | } 37 | 38 | - (id)init 39 | { 40 | if ((self = [super init])) 41 | { 42 | contextSet = [[DDLoggingContextSet alloc] init]; 43 | } 44 | return self; 45 | } 46 | 47 | 48 | - (void)addToWhitelist:(int)loggingContext 49 | { 50 | [contextSet addToSet:loggingContext]; 51 | } 52 | 53 | - (void)removeFromWhitelist:(int)loggingContext 54 | { 55 | [contextSet removeFromSet:loggingContext]; 56 | } 57 | 58 | - (NSArray *)whitelist 59 | { 60 | return [contextSet currentSet]; 61 | } 62 | 63 | - (BOOL)isOnWhitelist:(int)loggingContext 64 | { 65 | return [contextSet isInSet:loggingContext]; 66 | } 67 | 68 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage 69 | { 70 | if ([self isOnWhitelist:logMessage->logContext]) 71 | return logMessage->logMsg; 72 | else 73 | return nil; 74 | } 75 | 76 | @end 77 | 78 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 79 | #pragma mark - 80 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | 82 | @implementation DDContextBlacklistFilterLogFormatter 83 | { 84 | DDLoggingContextSet *contextSet; 85 | } 86 | 87 | - (id)init 88 | { 89 | if ((self = [super init])) 90 | { 91 | contextSet = [[DDLoggingContextSet alloc] init]; 92 | } 93 | return self; 94 | } 95 | 96 | 97 | - (void)addToBlacklist:(int)loggingContext 98 | { 99 | [contextSet addToSet:loggingContext]; 100 | } 101 | 102 | - (void)removeFromBlacklist:(int)loggingContext 103 | { 104 | [contextSet removeFromSet:loggingContext]; 105 | } 106 | 107 | - (NSArray *)blacklist 108 | { 109 | return [contextSet currentSet]; 110 | } 111 | 112 | - (BOOL)isOnBlacklist:(int)loggingContext 113 | { 114 | return [contextSet isInSet:loggingContext]; 115 | } 116 | 117 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage 118 | { 119 | if ([self isOnBlacklist:logMessage->logContext]) 120 | return nil; 121 | else 122 | return logMessage->logMsg; 123 | } 124 | 125 | @end 126 | 127 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 128 | #pragma mark - 129 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 130 | 131 | @implementation DDLoggingContextSet 132 | { 133 | OSSpinLock lock; 134 | NSMutableSet *set; 135 | } 136 | 137 | - (id)init 138 | { 139 | if ((self = [super init])) 140 | { 141 | set = [[NSMutableSet alloc] init]; 142 | } 143 | return self; 144 | } 145 | 146 | 147 | - (void)addToSet:(int)loggingContext 148 | { 149 | OSSpinLockLock(&lock); 150 | { 151 | [set addObject:@(loggingContext)]; 152 | } 153 | OSSpinLockUnlock(&lock); 154 | } 155 | 156 | - (void)removeFromSet:(int)loggingContext 157 | { 158 | OSSpinLockLock(&lock); 159 | { 160 | [set removeObject:@(loggingContext)]; 161 | } 162 | OSSpinLockUnlock(&lock); 163 | } 164 | 165 | - (NSArray *)currentSet 166 | { 167 | NSArray *result = nil; 168 | 169 | OSSpinLockLock(&lock); 170 | { 171 | result = [set allObjects]; 172 | } 173 | OSSpinLockUnlock(&lock); 174 | 175 | return result; 176 | } 177 | 178 | - (BOOL)isInSet:(int)loggingContext 179 | { 180 | BOOL result = NO; 181 | 182 | OSSpinLockLock(&lock); 183 | { 184 | result = [set containsObject:@(loggingContext)]; 185 | } 186 | OSSpinLockUnlock(&lock); 187 | 188 | return result; 189 | } 190 | 191 | @end 192 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/Extensions/DDDispatchQueueLogFormatter.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "DDLog.h" 4 | 5 | 6 | /** 7 | * Welcome to Cocoa Lumberjack! 8 | * 9 | * The project page has a wealth of documentation if you have any questions. 10 | * https://github.com/CocoaLumberjack/CocoaLumberjack 11 | * 12 | * If you're new to the project you may wish to read the "Getting Started" page. 13 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted 14 | * 15 | * 16 | * This class provides a log formatter that prints the dispatch_queue label instead of the mach_thread_id. 17 | * 18 | * A log formatter can be added to any logger to format and/or filter its output. 19 | * You can learn more about log formatters here: 20 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomFormatters 21 | * 22 | * A typical NSLog (or DDTTYLogger) prints detailed info as [:]. 23 | * For example: 24 | * 25 | * 2011-10-17 20:21:45.435 AppName[19928:5207] Your log message here 26 | * 27 | * Where: 28 | * - 19928 = process id 29 | * - 5207 = thread id (mach_thread_id printed in hex) 30 | * 31 | * When using grand central dispatch (GCD), this information is less useful. 32 | * This is because a single serial dispatch queue may be run on any thread from an internally managed thread pool. 33 | * For example: 34 | * 35 | * 2011-10-17 20:32:31.111 AppName[19954:4d07] Message from my_serial_dispatch_queue 36 | * 2011-10-17 20:32:31.112 AppName[19954:5207] Message from my_serial_dispatch_queue 37 | * 2011-10-17 20:32:31.113 AppName[19954:2c55] Message from my_serial_dispatch_queue 38 | * 39 | * This formatter allows you to replace the standard [box:info] with the dispatch_queue name. 40 | * For example: 41 | * 42 | * 2011-10-17 20:32:31.111 AppName[img-scaling] Message from my_serial_dispatch_queue 43 | * 2011-10-17 20:32:31.112 AppName[img-scaling] Message from my_serial_dispatch_queue 44 | * 2011-10-17 20:32:31.113 AppName[img-scaling] Message from my_serial_dispatch_queue 45 | * 46 | * If the dispatch_queue doesn't have a set name, then it falls back to the thread name. 47 | * If the current thread doesn't have a set name, then it falls back to the mach_thread_id in hex (like normal). 48 | * 49 | * Note: If manually creating your own background threads (via NSThread/alloc/init or NSThread/detachNeThread), 50 | * you can use [[NSThread currentThread] setName:(NSString *)]. 51 | **/ 52 | @interface DDDispatchQueueLogFormatter : NSObject { 53 | @protected 54 | 55 | NSString *dateFormatString; 56 | } 57 | 58 | /** 59 | * Standard init method. 60 | * Configure using properties as desired. 61 | **/ 62 | - (id)init; 63 | 64 | /** 65 | * The minQueueLength restricts the minimum size of the [detail box]. 66 | * If the minQueueLength is set to 0, there is no restriction. 67 | * 68 | * For example, say a dispatch_queue has a label of "diskIO": 69 | * 70 | * If the minQueueLength is 0: [diskIO] 71 | * If the minQueueLength is 4: [diskIO] 72 | * If the minQueueLength is 5: [diskIO] 73 | * If the minQueueLength is 6: [diskIO] 74 | * If the minQueueLength is 7: [diskIO ] 75 | * If the minQueueLength is 8: [diskIO ] 76 | * 77 | * The default minQueueLength is 0 (no minimum, so [detail box] won't be padded). 78 | * 79 | * If you want every [detail box] to have the exact same width, 80 | * set both minQueueLength and maxQueueLength to the same value. 81 | **/ 82 | @property (assign) NSUInteger minQueueLength; 83 | 84 | /** 85 | * The maxQueueLength restricts the number of characters that will be inside the [detail box]. 86 | * If the maxQueueLength is 0, there is no restriction. 87 | * 88 | * For example, say a dispatch_queue has a label of "diskIO": 89 | * 90 | * If the maxQueueLength is 0: [diskIO] 91 | * If the maxQueueLength is 4: [disk] 92 | * If the maxQueueLength is 5: [diskI] 93 | * If the maxQueueLength is 6: [diskIO] 94 | * If the maxQueueLength is 7: [diskIO] 95 | * If the maxQueueLength is 8: [diskIO] 96 | * 97 | * The default maxQueueLength is 0 (no maximum, so [detail box] won't be truncated). 98 | * 99 | * If you want every [detail box] to have the exact same width, 100 | * set both minQueueLength and maxQueueLength to the same value. 101 | **/ 102 | @property (assign) NSUInteger maxQueueLength; 103 | 104 | /** 105 | * Sometimes queue labels have long names like "com.apple.main-queue", 106 | * but you'd prefer something shorter like simply "main". 107 | * 108 | * This method allows you to set such preferred replacements. 109 | * The above example is set by default. 110 | * 111 | * To remove/undo a previous replacement, invoke this method with nil for the 'shortLabel' parameter. 112 | **/ 113 | - (NSString *)replacementStringForQueueLabel:(NSString *)longLabel; 114 | - (void)setReplacementString:(NSString *)shortLabel forQueueLabel:(NSString *)longLabel; 115 | 116 | @end 117 | 118 | /** 119 | * Method declarations that make it easier to extend/modify DDDispatchQueueLogFormatter 120 | **/ 121 | @interface DDDispatchQueueLogFormatter (OverridableMethods) 122 | 123 | - (NSString *)stringFromDate:(NSDate *)date; 124 | - (NSString *)queueThreadLabelForLogMessage:(DDLogMessage *)logMessage; 125 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage; 126 | 127 | @end 128 | 129 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/Extensions/DDDispatchQueueLogFormatter.m: -------------------------------------------------------------------------------- 1 | #import "DDDispatchQueueLogFormatter.h" 2 | #import 3 | 4 | /** 5 | * Welcome to Cocoa Lumberjack! 6 | * 7 | * The project page has a wealth of documentation if you have any questions. 8 | * https://github.com/CocoaLumberjack/CocoaLumberjack 9 | * 10 | * If you're new to the project you may wish to read the "Getting Started" wiki. 11 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted 12 | **/ 13 | 14 | #if ! __has_feature(objc_arc) 15 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 16 | #endif 17 | 18 | 19 | @implementation DDDispatchQueueLogFormatter 20 | { 21 | int32_t atomicLoggerCount; 22 | NSDateFormatter *threadUnsafeDateFormatter; // Use [self stringFromDate] 23 | 24 | OSSpinLock lock; 25 | 26 | NSUInteger _minQueueLength; // _prefix == Only access via atomic property 27 | NSUInteger _maxQueueLength; // _prefix == Only access via atomic property 28 | NSMutableDictionary *_replacements; // _prefix == Only access from within spinlock 29 | } 30 | 31 | - (id)init 32 | { 33 | if ((self = [super init])) 34 | { 35 | dateFormatString = @"yyyy-MM-dd HH:mm:ss:SSS"; 36 | 37 | atomicLoggerCount = 0; 38 | threadUnsafeDateFormatter = nil; 39 | 40 | _minQueueLength = 0; 41 | _maxQueueLength = 0; 42 | _replacements = [[NSMutableDictionary alloc] init]; 43 | 44 | // Set default replacements: 45 | 46 | _replacements[@"com.apple.main-thread"] = @"main"; 47 | } 48 | return self; 49 | } 50 | 51 | 52 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 53 | #pragma mark Configuration 54 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 55 | 56 | @synthesize minQueueLength = _minQueueLength; 57 | @synthesize maxQueueLength = _maxQueueLength; 58 | 59 | - (NSString *)replacementStringForQueueLabel:(NSString *)longLabel 60 | { 61 | NSString *result = nil; 62 | 63 | OSSpinLockLock(&lock); 64 | { 65 | result = _replacements[longLabel]; 66 | } 67 | OSSpinLockUnlock(&lock); 68 | 69 | return result; 70 | } 71 | 72 | - (void)setReplacementString:(NSString *)shortLabel forQueueLabel:(NSString *)longLabel 73 | { 74 | OSSpinLockLock(&lock); 75 | { 76 | if (shortLabel) 77 | _replacements[longLabel] = shortLabel; 78 | else 79 | [_replacements removeObjectForKey:longLabel]; 80 | } 81 | OSSpinLockUnlock(&lock); 82 | } 83 | 84 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 85 | #pragma mark DDLogFormatter 86 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 87 | 88 | - (NSString *)stringFromDate:(NSDate *)date 89 | { 90 | int32_t loggerCount = OSAtomicAdd32(0, &atomicLoggerCount); 91 | 92 | if (loggerCount <= 1) 93 | { 94 | // Single-threaded mode. 95 | 96 | if (threadUnsafeDateFormatter == nil) 97 | { 98 | threadUnsafeDateFormatter = [[NSDateFormatter alloc] init]; 99 | [threadUnsafeDateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4]; 100 | [threadUnsafeDateFormatter setDateFormat:dateFormatString]; 101 | } 102 | 103 | [threadUnsafeDateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]]; 104 | return [threadUnsafeDateFormatter stringFromDate:date]; 105 | } 106 | else 107 | { 108 | // Multi-threaded mode. 109 | // NSDateFormatter is NOT thread-safe. 110 | 111 | NSString *key = @"DispatchQueueLogFormatter_NSDateFormatter"; 112 | 113 | NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary]; 114 | NSDateFormatter *dateFormatter = threadDictionary[key]; 115 | 116 | if (dateFormatter == nil) 117 | { 118 | dateFormatter = [[NSDateFormatter alloc] init]; 119 | [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4]; 120 | [dateFormatter setDateFormat:dateFormatString]; 121 | 122 | threadDictionary[key] = dateFormatter; 123 | } 124 | 125 | [dateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]]; 126 | return [dateFormatter stringFromDate:date]; 127 | } 128 | } 129 | 130 | - (NSString *)queueThreadLabelForLogMessage:(DDLogMessage *)logMessage 131 | { 132 | // As per the DDLogFormatter contract, this method is always invoked on the same thread/dispatch_queue 133 | 134 | NSUInteger minQueueLength = self.minQueueLength; 135 | NSUInteger maxQueueLength = self.maxQueueLength; 136 | 137 | // Get the name of the queue, thread, or machID (whichever we are to use). 138 | 139 | NSString *queueThreadLabel = nil; 140 | 141 | BOOL useQueueLabel = YES; 142 | BOOL useThreadName = NO; 143 | 144 | if (logMessage->queueLabel) 145 | { 146 | // If you manually create a thread, it's dispatch_queue will have one of the thread names below. 147 | // Since all such threads have the same name, we'd prefer to use the threadName or the machThreadID. 148 | 149 | char *names[] = { "com.apple.root.low-priority", 150 | "com.apple.root.default-priority", 151 | "com.apple.root.high-priority", 152 | "com.apple.root.low-overcommit-priority", 153 | "com.apple.root.default-overcommit-priority", 154 | "com.apple.root.high-overcommit-priority" }; 155 | 156 | int length = sizeof(names) / sizeof(char *); 157 | 158 | int i; 159 | for (i = 0; i < length; i++) 160 | { 161 | if (strcmp(logMessage->queueLabel, names[i]) == 0) 162 | { 163 | useQueueLabel = NO; 164 | useThreadName = [logMessage->threadName length] > 0; 165 | break; 166 | } 167 | } 168 | } 169 | else 170 | { 171 | useQueueLabel = NO; 172 | useThreadName = [logMessage->threadName length] > 0; 173 | } 174 | 175 | if (useQueueLabel || useThreadName) 176 | { 177 | NSString *fullLabel; 178 | NSString *abrvLabel; 179 | 180 | if (useQueueLabel) 181 | fullLabel = @(logMessage->queueLabel); 182 | else 183 | fullLabel = logMessage->threadName; 184 | 185 | OSSpinLockLock(&lock); 186 | { 187 | abrvLabel = _replacements[fullLabel]; 188 | } 189 | OSSpinLockUnlock(&lock); 190 | 191 | if (abrvLabel) 192 | queueThreadLabel = abrvLabel; 193 | else 194 | queueThreadLabel = fullLabel; 195 | } 196 | else 197 | { 198 | queueThreadLabel = [NSString stringWithFormat:@"%x", logMessage->machThreadID]; 199 | } 200 | 201 | // Now use the thread label in the output 202 | 203 | NSUInteger labelLength = [queueThreadLabel length]; 204 | 205 | // labelLength > maxQueueLength : truncate 206 | // labelLength < minQueueLength : padding 207 | // : exact 208 | 209 | if ((maxQueueLength > 0) && (labelLength > maxQueueLength)) 210 | { 211 | // Truncate 212 | 213 | return [queueThreadLabel substringToIndex:maxQueueLength]; 214 | } 215 | else if (labelLength < minQueueLength) 216 | { 217 | // Padding 218 | 219 | NSUInteger numSpaces = minQueueLength - labelLength; 220 | 221 | char spaces[numSpaces + 1]; 222 | memset(spaces, ' ', numSpaces); 223 | spaces[numSpaces] = '\0'; 224 | 225 | return [NSString stringWithFormat:@"%@%s", queueThreadLabel, spaces]; 226 | } 227 | else 228 | { 229 | // Exact 230 | 231 | return queueThreadLabel; 232 | } 233 | } 234 | 235 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage 236 | { 237 | NSString *timestamp = [self stringFromDate:(logMessage->timestamp)]; 238 | NSString *queueThreadLabel = [self queueThreadLabelForLogMessage:logMessage]; 239 | 240 | return [NSString stringWithFormat:@"%@ [%@] %@", timestamp, queueThreadLabel, logMessage->logMsg]; 241 | } 242 | 243 | - (void)didAddToLogger:(id )logger 244 | { 245 | OSAtomicIncrement32(&atomicLoggerCount); 246 | } 247 | 248 | - (void)willRemoveFromLogger:(id )logger 249 | { 250 | OSAtomicDecrement32(&atomicLoggerCount); 251 | } 252 | 253 | @end 254 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/Extensions/DDMultiFormatter.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "DDLog.h" 3 | 4 | /** 5 | * Welcome to Cocoa Lumberjack! 6 | * 7 | * The project page has a wealth of documentation if you have any questions. 8 | * https://github.com/CocoaLumberjack/CocoaLumberjack 9 | * 10 | * If you're new to the project you may wish to read the "Getting Started" page. 11 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted 12 | * 13 | * 14 | * This formatter can be used to chain different formatters together. 15 | * The log message will processed in the order of the formatters added. 16 | **/ 17 | 18 | @interface DDMultiFormatter : NSObject 19 | 20 | /** 21 | * Array of chained formatters 22 | */ 23 | @property (readonly) NSArray *formatters; 24 | 25 | - (void)addFormatter:(id)formatter; 26 | - (void)removeFormatter:(id)formatter; 27 | - (void)removeAllFormatters; 28 | - (BOOL)isFormattingWithFormatter:(id)formatter; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/Extensions/DDMultiFormatter.m: -------------------------------------------------------------------------------- 1 | #import "DDMultiFormatter.h" 2 | 3 | /** 4 | * Welcome to Cocoa Lumberjack! 5 | * 6 | * The project page has a wealth of documentation if you have any questions. 7 | * https://github.com/CocoaLumberjack/CocoaLumberjack 8 | * 9 | * If you're new to the project you may wish to read the "Getting Started" page. 10 | * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted 11 | **/ 12 | 13 | #if TARGET_OS_IPHONE 14 | // Compiling for iOS 15 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 // iOS 6.0 or later 16 | #define NEEDS_DISPATCH_RETAIN_RELEASE 0 17 | #else // iOS 5.X or earlier 18 | #define NEEDS_DISPATCH_RETAIN_RELEASE 1 19 | #endif 20 | #else 21 | // Compiling for Mac OS X 22 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 // Mac OS X 10.8 or later 23 | #define NEEDS_DISPATCH_RETAIN_RELEASE 0 24 | #else // Mac OS X 10.7 or earlier 25 | #define NEEDS_DISPATCH_RETAIN_RELEASE 1 26 | #endif 27 | #endif 28 | 29 | 30 | @interface DDMultiFormatter () 31 | 32 | - (DDLogMessage *)logMessageForLine:(NSString *)line originalMessage:(DDLogMessage *)message; 33 | 34 | @end 35 | 36 | 37 | @implementation DDMultiFormatter { 38 | dispatch_queue_t _queue; 39 | NSMutableArray *_formatters; 40 | } 41 | 42 | - (id)init { 43 | self = [super init]; 44 | if (self) { 45 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 46 | _queue = dispatch_queue_create("cocoa.lumberjack.multiformatter", DISPATCH_QUEUE_CONCURRENT); 47 | #else 48 | _queue = dispatch_queue_create("cocoa.lumberjack.multiformatter", NULL); 49 | #endif 50 | _formatters = [NSMutableArray new]; 51 | } 52 | 53 | return self; 54 | } 55 | 56 | #if NEEDS_DISPATCH_RETAIN_RELEASE 57 | - (void)dealloc { 58 | dispatch_release(_queue); 59 | } 60 | #endif 61 | 62 | #pragma mark Processing 63 | 64 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage { 65 | __block NSString *line = logMessage->logMsg; 66 | 67 | dispatch_sync(_queue, ^{ 68 | for (id formatter in _formatters) { 69 | DDLogMessage *message = [self logMessageForLine:line originalMessage:logMessage]; 70 | line = [formatter formatLogMessage:message]; 71 | 72 | if (!line) { 73 | break; 74 | } 75 | } 76 | }); 77 | 78 | return line; 79 | } 80 | 81 | - (DDLogMessage *)logMessageForLine:(NSString *)line originalMessage:(DDLogMessage *)message { 82 | DDLogMessage *newMessage = [message copy]; 83 | newMessage->logMsg = line; 84 | return newMessage; 85 | } 86 | 87 | #pragma mark Formatters 88 | 89 | - (NSArray *)formatters { 90 | __block NSArray *formatters; 91 | 92 | dispatch_sync(_queue, ^{ 93 | formatters = [_formatters copy]; 94 | }); 95 | 96 | return formatters; 97 | } 98 | 99 | - (void)addFormatter:(id)formatter { 100 | dispatch_barrier_async(_queue, ^{ 101 | [_formatters addObject:formatter]; 102 | }); 103 | } 104 | 105 | - (void)removeFormatter:(id)formatter { 106 | dispatch_barrier_async(_queue, ^{ 107 | [_formatters removeObject:formatter]; 108 | }); 109 | } 110 | 111 | - (void)removeAllFormatters { 112 | dispatch_barrier_async(_queue, ^{ 113 | [_formatters removeAllObjects]; 114 | }); 115 | } 116 | 117 | - (BOOL)isFormattingWithFormatter:(id)formatter { 118 | __block BOOL hasFormatter; 119 | 120 | dispatch_sync(_queue, ^{ 121 | hasFormatter = [_formatters containsObject:formatter]; 122 | }); 123 | 124 | return hasFormatter; 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/CocoaLumberjack/Extensions/README.txt: -------------------------------------------------------------------------------- 1 | This folder contains some sample formatters that may be helpful. 2 | 3 | Feel free to change them, extend them, or use them as the basis for your own custom formatter(s). 4 | 5 | More information about creating your own custom formatters can be found on the wiki: 6 | https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomFormatters 7 | 8 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Externals/ffmpeg/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviLeo/DLGPlayer/3fa4895d0c958cd5d725bd2c4bed514692a9ddff/Example/DLGPlayer/Externals/ffmpeg/.gitignore -------------------------------------------------------------------------------- /Example/DLGPlayer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIFileSharingEnabled 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Example/DLGPlayer/MainViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.h 3 | // DLGPlayer 4 | // 5 | // Created by DeviLeo on 2017/2/26. 6 | // Copyright © 2017年 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MainViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Resources/web/index.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | top: 0px; 3 | right: 0px; 4 | bottom: 0px; 5 | left: 0px; 6 | width:1024px; 7 | height: 100%; 8 | margin: auto; 9 | } 10 | 11 | .area_uploading { 12 | width:500px; 13 | margin-right:10px; 14 | float:left; 15 | } 16 | 17 | .area_uploaded { 18 | width:500px; 19 | margin-left:10px; 20 | float:right; 21 | } 22 | 23 | .area_files_outer { 24 | height:400px; 25 | border-color:black; 26 | border-style:solid; 27 | border-width:1px; 28 | } 29 | .area_files_inner { 30 | width:100%; 31 | height:379px; 32 | overflow-x:hidden; 33 | overflow-y:auto; 34 | } 35 | 36 | .table_header { 37 | table-layout:fixed; 38 | border-collapse:collapse; 39 | border-bottom-style:solid; 40 | border-bottom-width:1px; 41 | } 42 | 43 | .uploading_table_header_col_0 { 44 | width:20px; 45 | overflow:hidden; 46 | border-right-style:solid; 47 | border-right-width:1px; 48 | } 49 | .uploading_table_header_col_1 { 50 | width:280px; 51 | overflow:hidden; 52 | text-align:center; 53 | border-right-style:solid; 54 | border-right-width:1px; 55 | } 56 | .uploading_table_header_col_2 { 57 | width:100px; 58 | overflow:hidden; 59 | text-align:center; 60 | } 61 | .uploading_table_header_col_3 { 62 | width:100px; 63 | overflow:hidden; 64 | text-align:center; 65 | border-left-style:solid; 66 | border-left-width:1px; 67 | } 68 | 69 | .table_content { 70 | table-layout:fixed; 71 | border-collapse:collapse; 72 | } 73 | 74 | .uploading_tr_0 { 75 | max-width:20px; 76 | min-width:20px; 77 | width:20px; 78 | } 79 | .uploading_tr_1 { 80 | max-width:270px; 81 | min-width:270px; 82 | width:270px; 83 | word-wrap:break-word; 84 | } 85 | .uploading_tr_2 { 86 | max-width:100px; 87 | min-width:100px; 88 | width:100px; 89 | text-align:center; 90 | word-wrap:break-word; 91 | } 92 | .uploading_tr_3 { 93 | max-width:100px; 94 | min-width:100px; 95 | width:100px; 96 | text-align:center; 97 | word-wrap:break-word; 98 | } 99 | 100 | .uploaded_table_header_col_0 { 101 | width:20px; 102 | overflow:hidden; 103 | border-right-style:solid; 104 | border-right-width:1px; 105 | } 106 | .uploaded_table_header_col_1 { 107 | width:380px; 108 | overflow:hidden; 109 | text-align:center; 110 | border-right-style:solid; 111 | border-right-width:1px; 112 | } 113 | .uploaded_table_header_col_2 { 114 | width:100px; 115 | overflow:hidden; 116 | text-align:center; 117 | } 118 | 119 | .uploaded_tr_0 { 120 | max-width:20px; 121 | min-width:20px; 122 | width:20px; 123 | } 124 | .uploaded_tr_1 { 125 | max-width:370px; 126 | min-width:370px; 127 | width:370px; 128 | word-wrap:break-word; 129 | } 130 | .uploaded_tr_2 { 131 | max-width:100px; 132 | min-width:100px; 133 | width:100px; 134 | text-align:center; 135 | word-wrap:break-word; 136 | } -------------------------------------------------------------------------------- /Example/DLGPlayer/Resources/web/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 文件管理 7 | 8 | 9 | 10 | 13 | 14 | 15 | 19 | 20 |
    21 |

    文件管理

    22 | 23 |
    24 | 25 |

    上传列表

    26 | 27 |
    28 |
    29 | 30 | 31 | 34 | 35 | 36 | 37 | 38 |
    32 | 33 | 文件名大小已上传
    39 |
    40 |
    41 | 42 |
    43 |
    44 |
    45 | 46 |
    47 | 48 |
    49 |
    50 |
    51 |
    52 | 53 |
    54 | 55 | 56 |
    57 | 58 |
    59 |
    60 | 61 | 62 |
    63 | 64 |

    文件列表

    65 | 66 |
    67 |
    68 | 69 | 70 | 73 | 74 | 75 | 76 |
    71 | 72 | 文件名大小
    77 |
    78 |
    79 | 80 | %MyFiles% 81 |
    82 |
    83 |
    84 | 85 | 86 |
    87 | 88 |
    89 |
    90 |
    91 |
    92 | 93 | 94 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Resources/web/js_disabled.css: -------------------------------------------------------------------------------- 1 | div#content { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Resources/web/js_enabled.css: -------------------------------------------------------------------------------- 1 | div#content { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /Example/DLGPlayer/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 29/11/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @property (nonatomic) NSString *url; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /Example/DLGPlayer/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 29/11/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "DLGPlayerViewController.h" 11 | 12 | @interface ViewController () 13 | 14 | @property (nonatomic, weak) IBOutlet UIView *vContainer; 15 | @property (nonatomic, weak) IBOutlet UITextField *tfUrl; 16 | @property (nonatomic) DLGPlayerViewController *vcDLGPlayer; 17 | @property (nonatomic) BOOL fullscreen; 18 | @property (nonatomic) BOOL landscape; 19 | 20 | @end 21 | 22 | @implementation ViewController 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | // Do any additional setup after loading the view, typically from a nib. 27 | _tfUrl.delegate = self; 28 | _tfUrl.text = _url; 29 | [self updateTitle]; 30 | } 31 | 32 | - (void)viewWillAppear:(BOOL)animated { 33 | [super viewWillAppear:animated]; 34 | } 35 | 36 | - (void)viewWillDisappear:(BOOL)animated { 37 | [super viewWillDisappear:animated]; 38 | [_vcDLGPlayer close]; 39 | [self unregisterNotification]; 40 | } 41 | 42 | - (void)viewDidAppear:(BOOL)animated { 43 | [super viewDidAppear:animated]; 44 | [self initDLGPlayer]; 45 | [self registerNotification]; 46 | [self go]; 47 | } 48 | 49 | - (void)didReceiveMemoryWarning { 50 | [super didReceiveMemoryWarning]; 51 | // Dispose of any resources that can be recreated. 52 | } 53 | 54 | 55 | - (void)registerNotification { 56 | NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 57 | [nc addObserver:self selector:@selector(notifyPlayerError:) name:DLGPlayerNotificationError object:_vcDLGPlayer]; 58 | } 59 | 60 | - (void)unregisterNotification { 61 | NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 62 | [nc removeObserver:self]; 63 | } 64 | 65 | - (void)notifyPlayerError:(NSNotification *)notif { 66 | NSDictionary *userInfo = notif.userInfo; 67 | NSError *error = userInfo[DLGPlayerNotificationErrorKey]; 68 | BOOL isAudioError = [error.domain isEqualToString:DLGPlayerErrorDomainAudioManager]; 69 | NSString *title = isAudioError ? @"Audio Error" : @"Error"; 70 | NSString *message = error.localizedDescription; 71 | if (isAudioError) { 72 | NSError *rawError = error.userInfo[NSLocalizedFailureReasonErrorKey]; 73 | message = [message stringByAppendingFormat:@"\n%@", rawError]; 74 | } 75 | 76 | dispatch_async(dispatch_get_main_queue(), ^{ 77 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:title 78 | message:message 79 | preferredStyle:UIAlertControllerStyleAlert]; 80 | UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" 81 | style:UIAlertActionStyleCancel 82 | handler:nil]; 83 | [alert addAction:ok]; 84 | [self presentViewController:alert animated:YES completion:nil]; 85 | }); 86 | } 87 | 88 | - (void)updateTitle { 89 | if (_tfUrl.text.length == 0) { 90 | self.navigationItem.title = @"DLGPlayer"; 91 | } else { 92 | self.navigationItem.title = [_tfUrl.text lastPathComponent]; 93 | } 94 | } 95 | 96 | #pragma mark - UITextFieldDelegate 97 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { 98 | if (textField.returnKeyType == UIReturnKeyGo) { 99 | [textField resignFirstResponder]; 100 | [self go]; 101 | } 102 | return YES; 103 | } 104 | 105 | - (void)go { 106 | if (_tfUrl.text.length == 0) return; 107 | [self updateTitle]; 108 | _vcDLGPlayer.url = _tfUrl.text; 109 | [_vcDLGPlayer close]; 110 | [_vcDLGPlayer open]; 111 | } 112 | 113 | - (void)initDLGPlayer { 114 | if (_vcDLGPlayer != nil) { 115 | [_vcDLGPlayer.view removeFromSuperview]; 116 | self.vcDLGPlayer = nil; 117 | } 118 | DLGPlayerViewController *vc = [[DLGPlayerViewController alloc] init]; 119 | vc.view.translatesAutoresizingMaskIntoConstraints = YES; 120 | vc.view.frame = self.vContainer.frame; 121 | vc.autoplay = YES; 122 | vc.repeat = YES; 123 | vc.preventFromScreenLock = YES; 124 | vc.restorePlayAfterAppEnterForeground = YES; 125 | [self.view addSubview:vc.view]; 126 | self.vcDLGPlayer = vc; 127 | } 128 | 129 | - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { 130 | [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; 131 | BOOL isLandscape = size.width > size.height; 132 | [coordinator animateAlongsideTransition:nil 133 | completion:^(id _Nonnull context) { 134 | self.landscape = isLandscape; 135 | }]; 136 | } 137 | 138 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 139 | [super touchesBegan:touches withEvent:event]; 140 | if ([_tfUrl canResignFirstResponder]) [_tfUrl resignFirstResponder]; 141 | 142 | UITouch *touch = [touches anyObject]; 143 | if (touch.tapCount == 2) { 144 | self.fullscreen = !self.fullscreen; 145 | } 146 | } 147 | 148 | - (void)setFullscreen:(BOOL)fullscreen { 149 | _fullscreen = fullscreen; 150 | [self updatePlayerFrame]; 151 | } 152 | 153 | - (void)setLandscape:(BOOL)landscape { 154 | _landscape = landscape; 155 | [self updatePlayerFrame]; 156 | } 157 | 158 | - (void)updatePlayerFrame { 159 | BOOL fullscreen = _landscape || _fullscreen; 160 | [self.navigationController setNavigationBarHidden:fullscreen animated:YES]; 161 | [[UIApplication sharedApplication] setStatusBarHidden:fullscreen withAnimation:YES]; 162 | [self setNeedsStatusBarAppearanceUpdate]; 163 | [UIView animateWithDuration:0.2f 164 | animations:^{ 165 | _vcDLGPlayer.view.frame = fullscreen ? self.view.frame : _vContainer.frame; 166 | }]; 167 | } 168 | 169 | - (BOOL)prefersStatusBarHidden { 170 | return (_landscape || _fullscreen); 171 | } 172 | 173 | @end 174 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Web/FileManagementViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FileManagementViewController.h 3 | // DLGPlayer 4 | // 5 | // Created by DeviLeo on 2017/2/26. 6 | // Copyright © 2017年 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define FMVNotificationAddUrlToHistory @"FMVNotificationAddUrlToHistory" 12 | 13 | @interface FileManagementViewController : UIViewController 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Web/HTTPUploader.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HTTPConnection.h" 3 | 4 | @class MultipartFormDataParser; 5 | 6 | #define HttpUploadNotificationRefreshFileList @"HttpUploadNotificationRefreshFileList" 7 | 8 | @interface HTTPUploader : HTTPConnection { 9 | MultipartFormDataParser* parser; 10 | NSFileHandle* storeFile; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Web/WebUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // WebUtils.h 3 | // DLGPlayer 4 | // 5 | // Created by DeviLeo on 2017/2/26. 6 | // Copyright © 2017年 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WebUtils : NSObject 12 | 13 | + (BOOL)getIpAddress:(NSString **)ipv4 ipv6:(NSString **)ipv6; 14 | + (BOOL)getIpAddressByName:(NSString *)ifa_name ipv4:(NSString **)ipv4 ipv6:(NSString **)ipv6; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Example/DLGPlayer/Web/WebUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // WebUtils.m 3 | // DLGPlayer 4 | // 5 | // Created by DeviLeo on 2017/2/26. 6 | // Copyright © 2017年 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import "WebUtils.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | @implementation WebUtils 16 | 17 | + (BOOL)getIpAddress:(NSString **)ipv4 ipv6:(NSString **)ipv6 { 18 | #if TARGET_IPHONE_SIMULATOR 19 | return [WebUtils getIpAddressByName:@"en1" ipv4:ipv4 ipv6:ipv6]; 20 | #else 21 | return [WebUtils getIpAddressByName:@"en0" ipv4:ipv4 ipv6:ipv6]; 22 | #endif 23 | } 24 | 25 | + (BOOL)getIpAddressByName:(NSString *)ifa_name ipv4:(NSString **)ipv4 ipv6:(NSString **)ipv6 { 26 | NSString *ipv4addr = nil; 27 | NSString *ipv6addr = nil; 28 | struct ifaddrs *interfaces = NULL; 29 | struct ifaddrs *temp_addr = NULL; 30 | int success = 0; 31 | 32 | // retrieve the current interfaces - returns 0 on success 33 | success = getifaddrs(&interfaces); 34 | if (success == 0) { 35 | // Loop through linked list of interfaces 36 | temp_addr = interfaces; 37 | while(temp_addr != NULL) { 38 | sa_family_t family = temp_addr->ifa_addr->sa_family; 39 | if(family == AF_INET) { 40 | NSString *ifa = [NSString stringWithUTF8String:temp_addr->ifa_name]; 41 | // Check if interface is en0 which is the wifi connection on the iPhone 42 | if([ifa isEqualToString:ifa_name]) { 43 | // Get NSString from C String 44 | char ip[INET_ADDRSTRLEN]; 45 | struct sockaddr_in *addr = (struct sockaddr_in *)temp_addr->ifa_addr; 46 | const char *ch = inet_ntop(AF_INET, &addr->sin_addr, ip, INET_ADDRSTRLEN); 47 | ipv4addr = [NSString stringWithUTF8String:ch]; 48 | if ([ipv4addr rangeOfString:@"169.254."].location == 0) ipv4addr = nil; 49 | } 50 | } else if (family == AF_INET6) { 51 | NSString *ifa = [NSString stringWithUTF8String:temp_addr->ifa_name]; 52 | 53 | // Check if interface is en0 which is the wifi connection on the iPhone 54 | if([ifa isEqualToString:ifa_name]) { 55 | // Get NSString from C String 56 | char ip[INET6_ADDRSTRLEN]; 57 | struct sockaddr_in6 *addr = (struct sockaddr_in6 *)temp_addr->ifa_addr; 58 | const char *ch = inet_ntop(AF_INET6, &addr->sin6_addr, ip, INET6_ADDRSTRLEN); 59 | ipv6addr = [NSString stringWithUTF8String:ch]; 60 | if ([ipv6addr rangeOfString:@"fe80::" options:NSCaseInsensitiveSearch].location == 0) ipv6addr = nil; 61 | } 62 | } 63 | temp_addr = temp_addr->ifa_next; 64 | } 65 | } 66 | 67 | // Free memory 68 | freeifaddrs(interfaces); 69 | 70 | if (ipv4addr == nil && ipv6addr == nil) return NO; 71 | 72 | if (ipv4 != nil) *ipv4 = ipv4addr; 73 | if (ipv6 != nil) *ipv6 = ipv6addr; 74 | return YES; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /Example/DLGPlayer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // DLGPlayer 4 | // 5 | // Created by Liu Junqi on 29/11/2016. 6 | // Copyright © 2016 Liu Junqi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /How_to_build_ffmpeg_with_openssl.md: -------------------------------------------------------------------------------- 1 | ## 1. Download OpenSSL source from [OpenSSL official site](https://www.openssl.org "https://www.openssl.org") 2 | Download openssl-1.0.2o.tar.gz 3 | **DO NOT** use OpenSSL 1.1.0, because FFmpeg 4.0 is not compatible for now. 4 | 5 | ## 2. Use [x2on/OpenSSL-for-iPhone](https://github.com/x2on/OpenSSL-for-iPhone "https://github.com/x2on/OpenSSL-for-iPhone") to build OpenSSL for iOS 6 | Follow the steps in the [README.md](https://github.com/x2on/OpenSSL-for-iPhone "https://github.com/x2on/OpenSSL-for-iPhone") of [x2on/OpenSSL-for-iPhone](https://github.com/x2on/OpenSSL-for-iPhone "https://github.com/x2on/OpenSSL-for-iPhone") to build OpenSSL for iOS. 7 | You need to edit __build-libssl.sh__ since the default version may be others. 8 | ``` 9 | # Change default version to 1.0.2o 10 | DEFAULTVERSION="1.0.2o" 11 | ``` 12 | 13 | ## 3. Copy built OpenSSL include files and libraries into a temporary folder 14 | After built successfully, you will find "include" and "lib" folders. 15 | Copy them into a temporary folder, and you can name it to "openssl". 16 | 17 | ## 4. Edit build-ffmpeg.sh file 18 | #### (1) Download [kewlbear/FFmpeg-iOS-build-script](https://github.com/kewlbear/FFmpeg-iOS-build-script "https://github.com/kewlbear/FFmpeg-iOS-build-script") 19 | Download [kewlbear/FFmpeg-iOS-build-script](https://github.com/kewlbear/FFmpeg-iOS-build-script "https://github.com/kewlbear/FFmpeg-iOS-build-script") and you will see the **"FFmpeg-iOS-build-script"** folder. 20 | 21 | #### (2) Duplicate "build-ffmpeg.sh" 22 | Make a copy of **"build-ffmpeg.sh"** and rename it to **"build-ffmpeg-openssl.sh"**. 23 | 24 | #### (3) Edit "build-ffmpeg-openssl.sh" 25 | Add the scripts between **##### Add Begin #####** and **##### Add End #####** to build with OpenSSL: 26 | ```bash 27 | 28 | ... 29 | 30 | ##### Change Begin ##### 31 | FF_VERSION="4.0" 32 | ##### Change End ##### 33 | 34 | ... 35 | 36 | #FDK_AAC=`pwd`/../fdk-aac-build-script-for-iOS/fdk-aac-ios 37 | 38 | ##### Add Begin ##### 39 | # OpenSSL 40 | OPENSSL=`pwd`/openssl 41 | ##### Add End ##### 42 | 43 | CONFIGURE_FLAGS="--enable-cross-compile --disable-debug --disable-programs \ 44 | --disable-doc --enable-pic" 45 | 46 | ... 47 | 48 | if [ "$FDK_AAC" ] 49 | then 50 | CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-libfdk-aac" 51 | fi 52 | 53 | ##### Add Begin ##### 54 | if [ "$OPENSSL" ] 55 | then 56 | CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-openssl" 57 | fi 58 | ##### Add End ##### 59 | 60 | # avresample 61 | #CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-avresample" 62 | 63 | ... 64 | 65 | if [ "$FDK_AAC" ] 66 | then 67 | CFLAGS="$CFLAGS -I$FDK_AAC/include" 68 | LDFLAGS="$LDFLAGS -L$FDK_AAC/lib" 69 | fi 70 | 71 | ##### Add Begin ##### 72 | if [ "$OPENSSL" ] 73 | then 74 | CFLAGS="$CFLAGS -I$OPENSSL/include" 75 | LDFLAGS="$LDFLAGS -L$OPENSSL/lib" 76 | fi 77 | ##### Add End ##### 78 | 79 | TMPDIR=${TMPDIR/%\/} $CWD/$SOURCE/configure \ 80 | 81 | ... 82 | 83 | ``` 84 | 85 | ## 5. Move "openssl" folder into "FFmpeg-iOS-build-script" folder 86 | Move the **"openssl"** folder into the **"FFmpeg-iOS-build-script"** folder. 87 | Make sure the **"build-ffmpeg-openssl.sh"** file is under the **"FFmpeg-iOS-build-script"** folder, too. 88 | 89 | ## 6. Edit "audio_convert_neon.S" 90 | This step is especially for __FFmpeg 4.0 (armv7/armv7s)__. 91 | If you are about to compile __FFmpeg 4.0 (arm64/i386/x86_64)__ or __lower (armv7/armv7s/arm64/i386/x86_64)__, you can skip this step. 92 | Open the file "__ffmpeg-4.0/libswresample/arm/audio_convert_neon.S__". 93 | 94 | Delete `_swri_oldapi_conv_flt_to_s16_neon:` and `_swri_oldapi_conv_fltp_to_s16_2ch_neon:`. 95 | Change `_swri_oldapi_conv_flt_to_s16_neon` to `X(swri_oldapi_conv_flt_to_s16_neon)` and `_swri_oldapi_conv_fltp_to_s16_2ch_neon` to `X(swri_oldapi_conv_fltp_to_s16_2ch_neon)`. 96 | 97 | ``` 98 | ... 99 | 100 | function swri_oldapi_conv_flt_to_s16_neon, export=1 101 | // >> Delete Begin 102 | // _swri_oldapi_conv_flt_to_s16_neon: 103 | // << Delete End 104 | subs r2, r2, #8 105 | vld1.32 {q0}, [r1,:128]! 106 | vcvt.s32.f32 q8, q0, #31 107 | 108 | ... 109 | 110 | function swri_oldapi_conv_fltp_to_s16_2ch_neon, export=1 111 | // >> Delete Begin 112 | // _swri_oldapi_conv_fltp_to_s16_2ch_neon: 113 | // << Delete End 114 | ldm r1, {r1, r3} 115 | subs r2, r2, #8 116 | vld1.32 {q0}, [r1,:128]! 117 | 118 | ... 119 | 120 | function swri_oldapi_conv_fltp_to_s16_nch_neon, export=1 121 | cmp r3, #2 122 | itt lt 123 | ldrlt r1, [r1] 124 | // >> Change Begin 125 | // blt _swri_oldapi_conv_flt_to_s16_neon 126 | // beq _swri_oldapi_conv_fltp_to_s16_2ch_neon 127 | blt X(swri_oldapi_conv_flt_to_s16_neon) 128 | beq X(swri_oldapi_conv_fltp_to_s16_2ch_neon) 129 | // << Change End 130 | 131 | push {r4-r8, lr} 132 | cmp r3, #4 133 | lsl r12, r3, #1 134 | blt 4f 135 | 136 | ... 137 | 138 | ``` 139 | 140 | ## 7. Run "build-ffmpeg-openssl.sh" 141 | Run and wait. 142 | 143 | ## 8. Put built FFmpeg include files and libraries into "DLGPlayer/Externals/ffmpeg" folder 144 | Put built **"ffmpeg/include"** and **"ffmpeg/lib"** folders into the example project's **"DLGPlayer/Externals/ffmpeg"** folder. 145 | 146 | ## 9. Add OpenSSL into the example project 147 | Put **"openssl"** folder into the example project's **"DLGPlayer/Externals"** folder. 148 | In Xcode, right click **"Externals"** folder, choose **"Add Files to ..."**, select **"openssl"** folder and click **"Add"** button. 149 | 150 | ## 10. Run the demo 151 | Build the example project and run the demo on your device or simulator. 152 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DLGPlayer 2 | A media player for iOS based on FFmpeg 4.0. 3 | DLGPlayer uses [kolyvan/kxmovie](https://github.com/kolyvan/kxmovie "https://github.com/kolyvan/kxmovie") as reference when written and **NO deprecated** functions and methods are used. 4 | If you found any deprecated function or method, please submit an issue to me. 5 | Great thanks for Konstantin Boukreev's kxmovie. 6 | 7 | ## 0. Screenshots 8 | |Orientation|Audio|Video| 9 | |:---------:|:---:|:---:| 10 | |Portrait|![](https://github.com/DeviLeo/Screenshots/blob/master/DLGPlayer/Simulator%20Screen%20Shot%2022%20Dec%202016%2C%202.00.52%20PM.png)|![](https://github.com/DeviLeo/Screenshots/blob/master/DLGPlayer/Simulator%20Screen%20Shot%2022%20Dec%202016%2C%202.07.30%20PM.png)| 11 | |Landscape|![](https://github.com/DeviLeo/Screenshots/blob/master/DLGPlayer/Simulator%20Screen%20Shot%2022%20Dec%202016%2C%202.01.05%20PM.png)|![](https://github.com/DeviLeo/Screenshots/blob/master/DLGPlayer/Simulator%20Screen%20Shot%2022%20Dec%202016%2C%202.07.38%20PM.png)| 12 | 13 | ## 1. Build FFmpeg for iOS 14 | #### (0) Support https (Optional) 15 | If you want to build FFmpeg with OpenSSL to support https, please see [How to build FFmpeg with OpenSSL](How_to_build_ffmpeg_with_openssl.md "How_to_build_ffmpeg_with_openssl.md") first, or continue. 16 | 17 | #### (1) Download FFmpeg source from [FFmpeg official site](http://ffmpeg.org/download.html "http://ffmpeg.org/download.html"). 18 | Download and unzip ffmpeg-4.0.tar.bz2   19 | 20 | #### (2) Use [kewlbear/FFmpeg-iOS-build-script](https://github.com/kewlbear/FFmpeg-iOS-build-script "https://github.com/kewlbear/FFmpeg-iOS-build-script") to build FFmpeg for iOS 21 | Follow the steps in the [README.md](https://github.com/kewlbear/FFmpeg-iOS-build-script "https://github.com/kewlbear/FFmpeg-iOS-build-script") of [kewlbear/FFmpeg-iOS-build-script](https://github.com/kewlbear/FFmpeg-iOS-build-script "https://github.com/kewlbear/FFmpeg-iOS-build-script") to build FFmpeg for iOS. 22 | You need to edit __build-ffmpeg.sh__ since the default version may not be 4.0. 23 | ``` 24 | ##### Change Begin ##### 25 | FF_VERSION="4.0" 26 | ##### Change End ##### 27 | ``` 28 | 29 | You need to edit __audio_convert_neon.S__ if you are about to compile __FFmpeg 4.0 (armv7/armv7s)__. 30 | Open the file "__ffmpeg-4.0/libswresample/arm/audio_convert_neon.S__". 31 | 32 | Delete `_swri_oldapi_conv_flt_to_s16_neon:` and `_swri_oldapi_conv_fltp_to_s16_2ch_neon:`. 33 | Change `_swri_oldapi_conv_flt_to_s16_neon` to `X(swri_oldapi_conv_flt_to_s16_neon)` and `_swri_oldapi_conv_fltp_to_s16_2ch_neon` to `X(swri_oldapi_conv_fltp_to_s16_2ch_neon)`. 34 | 35 | ``` 36 | ... 37 | 38 | function swri_oldapi_conv_flt_to_s16_neon, export=1 39 | // >> Delete Begin 40 | // _swri_oldapi_conv_flt_to_s16_neon: 41 | // << Delete End 42 | subs r2, r2, #8 43 | vld1.32 {q0}, [r1,:128]! 44 | vcvt.s32.f32 q8, q0, #31 45 | 46 | ... 47 | 48 | function swri_oldapi_conv_fltp_to_s16_2ch_neon, export=1 49 | // >> Delete Begin 50 | // _swri_oldapi_conv_fltp_to_s16_2ch_neon: 51 | // << Delete End 52 | ldm r1, {r1, r3} 53 | subs r2, r2, #8 54 | vld1.32 {q0}, [r1,:128]! 55 | 56 | ... 57 | 58 | function swri_oldapi_conv_fltp_to_s16_nch_neon, export=1 59 | cmp r3, #2 60 | itt lt 61 | ldrlt r1, [r1] 62 | // >> Change Begin 63 | // blt _swri_oldapi_conv_flt_to_s16_neon 64 | // beq _swri_oldapi_conv_fltp_to_s16_2ch_neon 65 | blt X(swri_oldapi_conv_flt_to_s16_neon) 66 | beq X(swri_oldapi_conv_fltp_to_s16_2ch_neon) 67 | // << Change End 68 | 69 | push {r4-r8, lr} 70 | cmp r3, #4 71 | lsl r12, r3, #1 72 | blt 4f 73 | 74 | ... 75 | 76 | ``` 77 | 78 | #### (3) Put built FFmpeg include files and libraries into DLGPlayer/Externals/ffmpeg folder. 79 | Put built "ffmpeg/include" and "ffmpeg/lib" folders into example project's "DLGPlayer/Externals/ffmpeg" folder. 80 | 81 | ## 2. Run demo 82 | Build project and run demo on your device or simulator. 83 | 84 | ## 3. Play media 85 | #### (1) Put any media files such as mp4 or mp3 into your server's folder. 86 | Make sure those media files can be access by url (such as http://192.168.31.120/media.mp4) from browser. 87 | Then input "http://192.168.31.120/media.mp4" into the text box on the top of the main view and go! 88 | 89 | #### (2) Transfer any media files using file management. 90 | Select "Local Files" in the main view. 91 | Transfer the media files according to the tips on the top of the file management view. 92 | Select any one media file listed in the table and enjoy it! 93 | 94 | ## 4. Usage 95 | #### (1) Use *DLGPlayerViewController* to play a media file with HUD. 96 | ```Objective-C 97 | DLGPlayerViewController *vc = [[DLGPlayerViewController alloc] init]; 98 | vc.autoplay = YES; 99 | vc.repeat = YES; 100 | vc.preventFromScreenLock = YES; 101 | vc.restorePlayAfterAppEnterForeground = YES; 102 | vc.view.frame = self.view.frame; 103 | [self.view addSubview:vc.view]; 104 | vc.url = @"http://192.168.31.120/media.mp4"; 105 | [vc open]; 106 | ``` 107 | 108 | #### (2) Use *DLGPlayer* to play a media file without HUD. 109 | ```Objective-C 110 | DLGPlayer *player = [[DLGPlayer alloc] init]; 111 | UIView *v = player.playerView; 112 | v.frame = self.view.frame; 113 | [self.view addSubview:v]; 114 | [player open:@"http://192.168.31.120/media.mp4"]; 115 | [player play]; 116 | ``` 117 | See ***DLGPlayerViewController*** class for more usage details. 118 | 119 | ## 5. Required frameworks and libraries 120 | * Accelerate.framework 121 | * AudioToolbox.framework 122 | * CoreAudio.framework 123 | * CoreGraphics.framework 124 | * CoreMedia.framework 125 | * MediaPlayer.framework 126 | * OpenGLES.framework 127 | * QuartzCore.framework 128 | * VideoToolbox.framework 129 | * libiconv.tbd 130 | * libbz2.tbd 131 | * libz.tbd 132 | 133 | ## 6. References 134 | * [FFmpeg](http://ffmpeg.org "http://ffmpeg.org") 135 | * [kolyvan/kxmovie](https://github.com/kolyvan/kxmovie "https://github.com/kolyvan/kxmovie") 136 | * [kewlbear/FFmpeg-iOS-build-script](https://github.com/kewlbear/FFmpeg-iOS-build-script "https://github.com/kewlbear/FFmpeg-iOS-build-script") 137 | * [libav/gas-preprocessor](https://github.com/libav/gas-preprocessor "https://github.com/libav/gas-preprocessor") 138 | * [Yasm](http://yasm.tortall.net "http://yasm.tortall.net") 139 | * [CocoaAsyncSocket](https://github.com/robbiehanson/CocoaAsyncSocket "https://github.com/robbiehanson/CocoaAsyncSocket") 140 | * [CocoaHTTPServer](https://github.com/robbiehanson/CocoaHTTPServer "https://github.com/robbiehanson/CocoaHTTPServer") 141 | * [OpenSSL](https://www.openssl.org "https://www.openssl.org") 142 | * [x2on/OpenSSL-for-iPhone](https://github.com/x2on/OpenSSL-for-iPhone "https://github.com/x2on/OpenSSL-for-iPhone") 143 | * [An intro to modern OpenGL. Chapter 3: 3D transformation and projection](http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-3:-3D-transformation-and-projection.html "http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-3:-3D-transformation-and-projection.html") 144 | 145 | Thank you all! 146 | 147 | ## 7. License 148 | See [LICENSE](https://github.com/DeviLeo/DLGPlayer/blob/master/LICENSE "LGPL-3.0"). 149 | --------------------------------------------------------------------------------