Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e592b6741 | |||
| 68236d76ea | |||
| eb9268e83e | |||
| 4252c1b45d | |||
| dbf61906fd | |||
| 67b81d190b | |||
| 07451cb2e6 | |||
| 9153fda04e | |||
| 168cd85284 | |||
| 9cfa0c368e | |||
| c53433afa2 | |||
| d8aca1ec43 | |||
| d224c48cb9 | |||
| bc0c0d0cf2 | |||
| 568b3a5699 | |||
| 6c10b3c374 | |||
| 027ee073b4 | |||
| 0bd6246973 | |||
| a2d5924aa1 | |||
| 0b8d4c77fc | |||
| a9c7005b3d | |||
| 37ef63d8f7 | |||
| 06678acdcc | |||
| 1eec503a8b | |||
| 3b071cb5ff | |||
| 12e7218848 | |||
| 230ed02f31 | |||
| b189ca63a0 | |||
| 859976339f | |||
| 8823bbdc15 | |||
| a6e4ec93bd | |||
| 8e47ee2924 | |||
| 46a3e67ad0 | |||
| 06fe1615ed | |||
| a32ba73a88 | |||
| 6d00aa0dff | |||
| cd13e7e9d4 | |||
| 0a927032e4 | |||
| 785780f8b3 | |||
| b71fc0efca | |||
| 2d251d5150 | |||
| 2043330287 | |||
| 3cb6349c97 | |||
| b51035a267 | |||
| 0d0280b631 | |||
| f9f8199015 | |||
| d9a6ba7248 | |||
| 6264442f58 | |||
| 830ed0f3db | |||
| 6ef69bacf0 | |||
| d8b77ae214 | |||
| 499e54731d | |||
| da71b04aaf | |||
| 55a314b966 | |||
| 8fa821a944 | |||
| 0f69b7ea76 | |||
| 4d0fccdd70 | |||
| 5909657368 | |||
| 50bec46acc | |||
| dec8b87498 | |||
| f872de223d | |||
| f84f1ef0bd | |||
| 3bc3a85df3 | |||
| 520f98a6b3 | |||
| 4f72249c94 | |||
| 726ec86d77 | |||
| 15b0242305 | |||
| ece165a5d0 | |||
| de99ec9d7a | |||
| 39f0d8bdfe | |||
| 8708e48395 | |||
| 94e6cbf41b | |||
| a5b6360b1c | |||
| 09e5602464 | |||
| 4c7ce6c4ec | |||
| 5784504e38 | |||
| e73df7fd86 | |||
| 9a4b4a617d | |||
| 7d4d7b847e | |||
| 61cb8a8a7b | |||
| 8e2e451e9c | |||
| 88be5b33c6 | |||
| 50a8b610c4 | |||
| c1b3b5d8cc | |||
| 477b1f175f |
@@ -24,3 +24,5 @@ Icon?
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
xcuserdata
|
||||
xcshareddata
|
||||
*.idea
|
||||
|
||||
@@ -30,6 +30,41 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
1D5086651A711D060030B19C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 1D50865D1A711D050030B19C /* StreamingKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = A1E7C4C8188D57F50010896F;
|
||||
remoteInfo = StreamingKit;
|
||||
};
|
||||
1D5086671A711D060030B19C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 1D50865D1A711D050030B19C /* StreamingKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = A1E7C4D8188D57F60010896F;
|
||||
remoteInfo = StreamingKitTests;
|
||||
};
|
||||
1D5086691A711D060030B19C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 1D50865D1A711D050030B19C /* StreamingKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = A1A49969189E744400E2A2E2;
|
||||
remoteInfo = StreamingKitMac;
|
||||
};
|
||||
1D50866B1A711D060030B19C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 1D50865D1A711D050030B19C /* StreamingKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = A1A4997A189E744500E2A2E2;
|
||||
remoteInfo = StreamingKitMacTests;
|
||||
};
|
||||
1D50866D1A711D160030B19C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 1D50865D1A711D050030B19C /* StreamingKit.xcodeproj */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = A1E7C4C7188D57F50010896F;
|
||||
remoteInfo = StreamingKit;
|
||||
};
|
||||
A1115951188D686000641365 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = A1115929188D686000641365 /* Project object */;
|
||||
@@ -40,6 +75,7 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1D50865D1A711D050030B19C /* StreamingKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = StreamingKit.xcodeproj; path = ../StreamingKit/StreamingKit.xcodeproj; sourceTree = "<group>"; };
|
||||
A1115931188D686000641365 /* ExampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ExampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A1115934188D686000641365 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
A1115936188D686000641365 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||
@@ -97,6 +133,17 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
1D50865E1A711D050030B19C /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1D5086661A711D060030B19C /* libStreamingKit.a */,
|
||||
1D5086681A711D060030B19C /* StreamingKitTests.xctest */,
|
||||
1D50866A1A711D060030B19C /* libStreamingKitMac.a */,
|
||||
1D50866C1A711D060030B19C /* StreamingKitMacTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A1115928188D686000641365 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -119,6 +166,7 @@
|
||||
A1115933188D686000641365 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1D50865D1A711D050030B19C /* StreamingKit.xcodeproj */,
|
||||
A17FFB6218A0028300BAA7FF /* AudioToolbox.framework */,
|
||||
A1F5E491189EB3F20070B03F /* AVFoundation.framework */,
|
||||
A1F5E48F189EB3CB0070B03F /* AudioUnit.framework */,
|
||||
@@ -200,6 +248,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
1D50866E1A711D160030B19C /* PBXTargetDependency */,
|
||||
);
|
||||
name = ExampleApp;
|
||||
productName = ExampleApp;
|
||||
@@ -230,7 +279,7 @@
|
||||
A1115929188D686000641365 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0510;
|
||||
LastUpgradeCheck = 1010;
|
||||
ORGANIZATIONNAME = "Thong Nguyen";
|
||||
TargetAttributes = {
|
||||
A111594B188D686000641365 = {
|
||||
@@ -248,6 +297,12 @@
|
||||
mainGroup = A1115928188D686000641365;
|
||||
productRefGroup = A1115932188D686000641365 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
{
|
||||
ProductGroup = 1D50865E1A711D050030B19C /* Products */;
|
||||
ProjectRef = 1D50865D1A711D050030B19C /* StreamingKit.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
A1115930188D686000641365 /* ExampleApp */,
|
||||
@@ -256,6 +311,37 @@
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
1D5086661A711D060030B19C /* libStreamingKit.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libStreamingKit.a;
|
||||
remoteRef = 1D5086651A711D060030B19C /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
1D5086681A711D060030B19C /* StreamingKitTests.xctest */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.cfbundle;
|
||||
path = StreamingKitTests.xctest;
|
||||
remoteRef = 1D5086671A711D060030B19C /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
1D50866A1A711D060030B19C /* libStreamingKitMac.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libStreamingKitMac.a;
|
||||
remoteRef = 1D5086691A711D060030B19C /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
1D50866C1A711D060030B19C /* StreamingKitMacTests.xctest */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.cfbundle;
|
||||
path = StreamingKitMacTests.xctest;
|
||||
remoteRef = 1D50866B1A711D060030B19C /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
A111592F188D686000641365 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
@@ -301,6 +387,11 @@
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
1D50866E1A711D160030B19C /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = StreamingKit;
|
||||
targetProxy = 1D50866D1A711D160030B19C /* PBXContainerItemProxy */;
|
||||
};
|
||||
A1115952188D686000641365 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = A1115930188D686000641365 /* ExampleApp */;
|
||||
@@ -336,18 +427,32 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
@@ -365,7 +470,7 @@
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../StreamingKit/StreamingKit",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -380,18 +485,31 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
@@ -403,7 +521,7 @@
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../StreamingKit/StreamingKit",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
@@ -419,9 +537,10 @@
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch";
|
||||
INFOPLIST_FILE = "ExampleApp/ExampleApp-Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LLVM_LTO = YES;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
@@ -435,9 +554,10 @@
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch";
|
||||
INFOPLIST_FILE = "ExampleApp/ExampleApp-Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LLVM_LTO = YES;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
@@ -459,6 +579,7 @@
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = "ExampleAppTests/ExampleAppTests-Info.plist";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUNDLE_LOADER)";
|
||||
WRAPPER_EXTENSION = xctest;
|
||||
@@ -477,6 +598,7 @@
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch";
|
||||
INFOPLIST_FILE = "ExampleAppTests/ExampleAppTests-Info.plist";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUNDLE_LOADER)";
|
||||
WRAPPER_EXTENSION = xctest;
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
-(BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
|
||||
{
|
||||
NSError* error;
|
||||
Float32 bufferLength = 0.1;
|
||||
|
||||
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
|
||||
[[AVAudioSession sharedInstance] setPreferredIOBufferDuration:bufferLength error:&error];
|
||||
[[AVAudioSession sharedInstance] setActive:YES error:&error];
|
||||
|
||||
Float32 bufferLength = 0.1;
|
||||
AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(bufferLength), &bufferLength);
|
||||
|
||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
self.window.rootViewController = [[UIViewController alloc] init];
|
||||
|
||||
self.window.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
audioPlayer.meteringEnabled = YES;
|
||||
audioPlayer.volume = 1;
|
||||
|
||||
|
||||
AudioPlayerView* audioPlayerView = [[AudioPlayerView alloc] initWithFrame:self.window.bounds andAudioPlayer:audioPlayer];
|
||||
|
||||
audioPlayerView.delegate = self;
|
||||
@@ -47,9 +46,9 @@
|
||||
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
|
||||
[self becomeFirstResponder];
|
||||
|
||||
[self.window addSubview:audioPlayerView];
|
||||
|
||||
[self.window makeKeyAndVisible];
|
||||
|
||||
[self.window.rootViewController.view addSubview:audioPlayerView];
|
||||
|
||||
return YES;
|
||||
}
|
||||
@@ -70,7 +69,7 @@
|
||||
|
||||
-(void) audioPlayerViewPlayFromIcecastSelected:(AudioPlayerView *)audioPlayerView
|
||||
{
|
||||
NSURL* url = [NSURL URLWithString:@"http://shoutmedia.abc.net.au:10326"];
|
||||
NSURL* url = [NSURL URLWithString:@"http://nashe.streamr.ru/jazz-128.mp3"];
|
||||
|
||||
STKDataSource* dataSource = [STKAudioPlayer dataSourceFromURL:url];
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
@private
|
||||
NSTimer* timer;
|
||||
UILabel* label;
|
||||
UILabel* metadataLabel;
|
||||
UILabel* statusLabel;
|
||||
UISlider* slider;
|
||||
UISwitch* enableEqSwitch;
|
||||
|
||||
@@ -58,27 +58,27 @@
|
||||
CGSize size = CGSizeMake(220, 50);
|
||||
|
||||
playFromHTTPButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
||||
playFromHTTPButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10, size.width, size.height);
|
||||
playFromHTTPButton.frame = CGRectMake((frame.size.width - size.width) / 2, frame.size.height * 0.10, size.width, size.height);
|
||||
[playFromHTTPButton addTarget:self action:@selector(playFromHTTPButtonTouched) forControlEvents:UIControlEventTouchUpInside];
|
||||
[playFromHTTPButton setTitle:@"Play from HTTP" forState:UIControlStateNormal];
|
||||
|
||||
playFromIcecastButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
||||
playFromIcecastButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10 + 35, size.width, size.height);
|
||||
playFromIcecastButton.frame = CGRectMake((frame.size.width - size.width) / 2, frame.size.height * 0.10 + 35, size.width, size.height);
|
||||
[playFromIcecastButton addTarget:self action:@selector(playFromIcecasButtonTouched) forControlEvents:UIControlEventTouchUpInside];
|
||||
[playFromIcecastButton setTitle:@"Play from Icecast" forState:UIControlStateNormal];
|
||||
|
||||
playFromLocalFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
||||
playFromLocalFileButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10 + 70, size.width, size.height);
|
||||
playFromLocalFileButton.frame = CGRectMake((frame.size.width - size.width) / 2, frame.size.height * 0.10 + 70, size.width, size.height);
|
||||
[playFromLocalFileButton addTarget:self action:@selector(playFromLocalFileButtonTouched) forControlEvents:UIControlEventTouchUpInside];
|
||||
[playFromLocalFileButton setTitle:@"Play from Local File" forState:UIControlStateNormal];
|
||||
|
||||
queueShortFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
||||
queueShortFileButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10 + 105, size.width, size.height);
|
||||
queueShortFileButton.frame = CGRectMake((frame.size.width - size.width) / 2, frame.size.height * 0.10 + 105, size.width, size.height);
|
||||
[queueShortFileButton addTarget:self action:@selector(queueShortFileButtonTouched) forControlEvents:UIControlEventTouchUpInside];
|
||||
[queueShortFileButton setTitle:@"Queue short file" forState:UIControlStateNormal];
|
||||
|
||||
queuePcmWaveFileFromHTTPButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
||||
queuePcmWaveFileFromHTTPButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10 + 140, size.width, size.height);
|
||||
queuePcmWaveFileFromHTTPButton.frame = CGRectMake((frame.size.width - size.width) / 2, frame.size.height * 0.10 + 140, size.width, size.height);
|
||||
[queuePcmWaveFileFromHTTPButton addTarget:self action:@selector(queuePcmWaveFileButtonTouched) forControlEvents:UIControlEventTouchUpInside];
|
||||
[queuePcmWaveFileFromHTTPButton setTitle:@"Queue PCM/WAVE from HTTP" forState:UIControlStateNormal];
|
||||
|
||||
@@ -89,12 +89,12 @@
|
||||
[playButton addTarget:self action:@selector(playButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
stopButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
||||
stopButton.frame = CGRectMake((320 - size.width) - 30, 400, size.width, size.height);
|
||||
stopButton.frame = CGRectMake((frame.size.width - size.width) - 30, 400, size.width, size.height);
|
||||
[stopButton addTarget:self action:@selector(stopButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||
[stopButton setTitle:@"Stop" forState:UIControlStateNormal];
|
||||
|
||||
muteButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
||||
muteButton.frame = CGRectMake((320 - size.width) - 30, 430, size.width, size.height);
|
||||
muteButton.frame = CGRectMake((frame.size.width - size.width) - 30, 430, size.width, size.height);
|
||||
[muteButton addTarget:self action:@selector(muteButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||
[muteButton setTitle:@"Mute" forState:UIControlStateNormal];
|
||||
|
||||
@@ -106,11 +106,16 @@
|
||||
|
||||
repeatSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(30, frame.size.height * 0.15 + 180, size.width, size.height)];
|
||||
|
||||
enableEqSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(320 - size.width - 30, frame.size.height * 0.15 + 180, size.width, size.height)];
|
||||
enableEqSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(frame.size.width - size.width - 30, frame.size.height * 0.15 + 180, size.width, size.height)];
|
||||
enableEqSwitch.on = audioPlayer.equalizerEnabled;
|
||||
|
||||
[enableEqSwitch addTarget:self action:@selector(onEnableEqSwitch) forControlEvents:UIControlEventAllTouchEvents];
|
||||
|
||||
metadataLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, slider.frame.origin.y + slider.frame.size.height + 10, frame.size.width, 25)];
|
||||
|
||||
metadataLabel.textAlignment = NSTextAlignmentCenter;
|
||||
metadataLabel.font = [UIFont boldSystemFontOfSize:17.0f];
|
||||
|
||||
label = [[UILabel alloc] initWithFrame:CGRectMake(0, slider.frame.origin.y + slider.frame.size.height + 40, frame.size.width, 25)];
|
||||
|
||||
label.textAlignment = NSTextAlignmentCenter;
|
||||
@@ -131,6 +136,7 @@
|
||||
[self addSubview:queueShortFileButton];
|
||||
[self addSubview:queuePcmWaveFileFromHTTPButton];
|
||||
[self addSubview:repeatSwitch];
|
||||
[self addSubview:metadataLabel];
|
||||
[self addSubview:label];
|
||||
[self addSubview:statusLabel];
|
||||
[self addSubview:stopButton];
|
||||
@@ -218,26 +224,31 @@
|
||||
-(void) playFromHTTPButtonTouched
|
||||
{
|
||||
[self.delegate audioPlayerViewPlayFromHTTPSelected:self];
|
||||
metadataLabel.text = nil;
|
||||
}
|
||||
|
||||
-(void) playFromIcecasButtonTouched
|
||||
{
|
||||
[self.delegate audioPlayerViewPlayFromIcecastSelected:self];
|
||||
metadataLabel.text = nil;
|
||||
}
|
||||
|
||||
-(void) playFromLocalFileButtonTouched
|
||||
{
|
||||
[self.delegate audioPlayerViewPlayFromLocalFileSelected:self];
|
||||
metadataLabel.text = nil;
|
||||
}
|
||||
|
||||
-(void) queueShortFileButtonTouched
|
||||
{
|
||||
[self.delegate audioPlayerViewQueueShortFileSelected:self];
|
||||
metadataLabel.text = nil;
|
||||
}
|
||||
|
||||
-(void) queuePcmWaveFileButtonTouched
|
||||
{
|
||||
[self.delegate audioPlayerViewQueuePcmWaveFileSelected:self];
|
||||
metadataLabel.text = nil;
|
||||
}
|
||||
|
||||
-(void) muteButtonPressed
|
||||
@@ -375,4 +386,11 @@
|
||||
NSLog(@"%@", line);
|
||||
}
|
||||
|
||||
- (void)audioPlayer:(STKAudioPlayer *)audioPlayer didReadStreamMetadata:(NSDictionary *)dictionary
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self->metadataLabel.text = dictionary[@"StreamTitle"];
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
|
||||
@@ -5,16 +5,31 @@
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,31 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "iphone",
|
||||
"subtype" : "736h",
|
||||
"filename" : "TX6sV.png",
|
||||
"minimum-system-version" : "8.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "8.0",
|
||||
"subtype" : "736h",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "iphone",
|
||||
"subtype" : "667h",
|
||||
"filename" : "dBEHd.png",
|
||||
"minimum-system-version" : "8.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
@@ -8,11 +34,12 @@
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "iphone",
|
||||
"subtype" : "retina4",
|
||||
"extent" : "full-screen",
|
||||
"filename" : "TX6sV-2.png",
|
||||
"minimum-system-version" : "7.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
@@ -42,6 +69,26 @@
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "7.0",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "TX6sV-1.png",
|
||||
"extent" : "full-screen",
|
||||
"subtype" : "retina4",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.3 KiB |
@@ -7,7 +7,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
@@ -238,7 +238,7 @@
|
||||
A1A49999189E765800E2A2E2 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0500;
|
||||
LastUpgradeCheck = 1010;
|
||||
ORGANIZATIONNAME = "Thong Nguyen";
|
||||
TargetAttributes = {
|
||||
A1A499C1189E765800E2A2E2 = {
|
||||
@@ -358,18 +358,32 @@
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
@@ -382,7 +396,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
@@ -395,26 +409,39 @@
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
@@ -432,8 +459,8 @@
|
||||
"$(SRCROOT)/../StreamingKit/StreamingKit",
|
||||
);
|
||||
INFOPLIST_FILE = "ExampleAppMac/ExampleAppMac-Info.plist";
|
||||
MACOSX_DEPLOYMENT_TARGET = "";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.abstractpath.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
@@ -452,8 +479,8 @@
|
||||
"$(SRCROOT)/../StreamingKit/StreamingKit",
|
||||
);
|
||||
INFOPLIST_FILE = "ExampleAppMac/ExampleAppMac-Info.plist";
|
||||
MACOSX_DEPLOYMENT_TARGET = "";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.abstractpath.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
@@ -476,6 +503,7 @@
|
||||
);
|
||||
INFOPLIST_FILE = "ExampleAppMacTests/ExampleAppMacTests-Info.plist";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.abstractpath.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUNDLE_LOADER)";
|
||||
WRAPPER_EXTENSION = xctest;
|
||||
@@ -495,6 +523,7 @@
|
||||
GCC_PREFIX_HEADER = "ExampleAppMac/ExampleAppMac-Prefix.pch";
|
||||
INFOPLIST_FILE = "ExampleAppMacTests/ExampleAppMacTests-Info.plist";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.abstractpath.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUNDLE_LOADER)";
|
||||
WRAPPER_EXTENSION = xctest;
|
||||
|
||||
+6
-6
@@ -10,29 +10,29 @@
|
||||
<string>ExampleAppMac</string>
|
||||
<key>IDESourceControlProjectOriginsDictionary</key>
|
||||
<dict>
|
||||
<key>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</key>
|
||||
<key>3E9414865BAE5433092B9D136FFC1F054EA505C2</key>
|
||||
<string>https://github.com/tumtumtum/StreamingKit.git</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectPath</key>
|
||||
<string>ExampleAppMac/ExampleAppMac.xcodeproj/project.xcworkspace</string>
|
||||
<string>ExampleAppMac/ExampleAppMac.xcodeproj</string>
|
||||
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
|
||||
<dict>
|
||||
<key>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</key>
|
||||
<key>3E9414865BAE5433092B9D136FFC1F054EA505C2</key>
|
||||
<string>../../..</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectURL</key>
|
||||
<string>https://github.com/tumtumtum/StreamingKit.git</string>
|
||||
<key>IDESourceControlProjectVersion</key>
|
||||
<integer>110</integer>
|
||||
<integer>111</integer>
|
||||
<key>IDESourceControlProjectWCCIdentifier</key>
|
||||
<string>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</string>
|
||||
<string>3E9414865BAE5433092B9D136FFC1F054EA505C2</string>
|
||||
<key>IDESourceControlProjectWCConfigurations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
|
||||
<string>public.vcs.git</string>
|
||||
<key>IDESourceControlWCCIdentifierKey</key>
|
||||
<string>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</string>
|
||||
<string>3E9414865BAE5433092B9D136FFC1F054EA505C2</string>
|
||||
<key>IDESourceControlWCCName</key>
|
||||
<string>StreamingKit</string>
|
||||
</dict>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
NSView* meter;
|
||||
NSSlider* slider;
|
||||
STKAudioPlayer* audioPlayer;
|
||||
NSTextField* textField;
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -21,26 +22,67 @@
|
||||
|
||||
-(void) applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
CGRect frame = [self.window.contentView frame];
|
||||
|
||||
NSButton* playFromHTTPButton = [[NSButton alloc] initWithFrame:CGRectMake(10, 10, frame.size.width - 20, 100)];
|
||||
|
||||
NSButton* playFromHTTPButton = [[NSButton alloc] init];
|
||||
[playFromHTTPButton setTitle:@"Play from HTTP"];
|
||||
[playFromHTTPButton setAction:@selector(playFromHTTP)];
|
||||
|
||||
NSButton* stopButton = [[NSButton alloc] init];
|
||||
[stopButton setTitle:@"Stop"];
|
||||
[stopButton setAction:@selector(stopPlaying)];
|
||||
|
||||
NSStackView *buttonStackView = [[NSStackView alloc] initWithFrame:self.window.contentView.frame];
|
||||
[buttonStackView setDistribution:NSStackViewDistributionFillEqually];
|
||||
[buttonStackView setSpacing:8];
|
||||
[buttonStackView setOrientation:NSUserInterfaceLayoutOrientationHorizontal];
|
||||
|
||||
[buttonStackView addArrangedSubview:playFromHTTPButton];
|
||||
[buttonStackView addArrangedSubview:stopButton];
|
||||
|
||||
slider = [[NSSlider alloc] initWithFrame:CGRectMake(10, 140, frame.size.width - 20, 20)];
|
||||
slider = [[NSSlider alloc] init];
|
||||
[slider setTranslatesAutoresizingMaskIntoConstraints:false];
|
||||
[slider setAction:@selector(sliderChanged:)];
|
||||
|
||||
meter = [[NSView alloc] initWithFrame:CGRectMake(10, 200, 0, 20)];
|
||||
meter = [[NSView alloc] init];
|
||||
[meter setTranslatesAutoresizingMaskIntoConstraints:false];
|
||||
[meter setLayer:[CALayer new]];
|
||||
[meter setWantsLayer:YES];
|
||||
meter.layer.backgroundColor = [NSColor greenColor].CGColor;
|
||||
|
||||
[[self.window contentView] addSubview:slider];
|
||||
[[self.window contentView] addSubview:playFromHTTPButton];
|
||||
[[self.window contentView] addSubview:meter];
|
||||
|
||||
audioPlayer = [[STKAudioPlayer alloc] initWithOptions:(STKAudioPlayerOptions){ .enableVolumeMixer = NO, .equalizerBandFrequencies = {50, 100, 200, 400, 800, 1600, 2600, 16000} } ];
|
||||
|
||||
NSView *meterWrapper = [[NSView alloc] init];
|
||||
[meterWrapper setTranslatesAutoresizingMaskIntoConstraints:false];
|
||||
[meterWrapper addSubview:meter];
|
||||
|
||||
textField = [[NSTextField alloc] init];
|
||||
[textField setTranslatesAutoresizingMaskIntoConstraints:false];
|
||||
textField.stringValue = @"http://www.abstractpath.com/files/audiosamples/sample.mp3";
|
||||
|
||||
NSStackView *stackView = [[NSStackView alloc] initWithFrame:self.window.contentView.frame];
|
||||
[stackView setTranslatesAutoresizingMaskIntoConstraints:false];
|
||||
[stackView setDistribution:NSStackViewDistributionEqualSpacing];
|
||||
[stackView setSpacing:8];
|
||||
[stackView setOrientation:NSUserInterfaceLayoutOrientationVertical];
|
||||
|
||||
[stackView addArrangedSubview:textField];
|
||||
[stackView addArrangedSubview:meterWrapper];
|
||||
[stackView addArrangedSubview:slider];
|
||||
[stackView addArrangedSubview:buttonStackView];
|
||||
|
||||
[[self.window contentView] addSubview:stackView];
|
||||
|
||||
[stackView.topAnchor constraintEqualToAnchor:self.window.contentView.topAnchor constant:16].active = true;
|
||||
[stackView.bottomAnchor constraintEqualToAnchor:self.window.contentView.bottomAnchor constant:-16].active = true;
|
||||
[stackView.rightAnchor constraintEqualToAnchor:self.window.contentView.rightAnchor constant:-16].active = true;
|
||||
[stackView.leftAnchor constraintEqualToAnchor:self.window.contentView.leftAnchor constant:16].active = true;
|
||||
|
||||
[meter.topAnchor constraintEqualToAnchor:meterWrapper.topAnchor].active = true;
|
||||
[meter.bottomAnchor constraintEqualToAnchor:meterWrapper.bottomAnchor].active = true;
|
||||
[meter.leadingAnchor constraintEqualToAnchor:meterWrapper.leadingAnchor].active = true;
|
||||
|
||||
audioPlayer = [[STKAudioPlayer alloc] initWithOptions:(STKAudioPlayerOptions)
|
||||
{
|
||||
.enableVolumeMixer = NO,
|
||||
.equalizerBandFrequencies = {50, 100, 200, 400, 800, 1600, 2600, 16000}
|
||||
}];
|
||||
audioPlayer.delegate = self;
|
||||
audioPlayer.meteringEnabled = YES;
|
||||
audioPlayer.volume = 0.1;
|
||||
@@ -58,7 +100,13 @@
|
||||
|
||||
-(void) playFromHTTP
|
||||
{
|
||||
[audioPlayer play:@"http://www.abstractpath.com/files/audiosamples/sample.mp3"];
|
||||
[audioPlayer play:textField.stringValue];
|
||||
audioPlayer.rate = 2;
|
||||
}
|
||||
|
||||
- (void) stopPlaying
|
||||
{
|
||||
[audioPlayer stop];
|
||||
}
|
||||
|
||||
-(void) tick:(NSTimer*)timer
|
||||
|
||||
@@ -1,100 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4439" systemVersion="13A451" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4439"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" destination="58" id="142"/>
|
||||
<outlet property="delegate" destination="494" id="495"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder">
|
||||
<connections>
|
||||
<action selector="alignCenter:" destination="499" id="518"/>
|
||||
<action selector="alignJustified:" destination="500" id="523"/>
|
||||
<action selector="alignLeft:" destination="498" id="524"/>
|
||||
<action selector="alignRight:" destination="501" id="521"/>
|
||||
<action selector="arrangeInFront:" destination="5" id="39"/>
|
||||
<action selector="capitalizeWord:" destination="466" id="467"/>
|
||||
<action selector="centerSelectionInVisibleArea:" destination="210" id="245"/>
|
||||
<action selector="checkSpelling:" destination="201" id="225"/>
|
||||
<action selector="clearRecentDocuments:" destination="126" id="127"/>
|
||||
<action selector="copy:" destination="197" id="224"/>
|
||||
<action selector="copyFont:" destination="403" id="428"/>
|
||||
<action selector="copyRuler:" destination="506" id="522"/>
|
||||
<action selector="cut:" destination="199" id="228"/>
|
||||
<action selector="delete:" destination="202" id="235"/>
|
||||
<action selector="hide:" destination="134" id="367"/>
|
||||
<action selector="hideOtherApplications:" destination="145" id="368"/>
|
||||
<action selector="loosenKerning:" destination="419" id="435"/>
|
||||
<action selector="lowerBaseline:" destination="410" id="427"/>
|
||||
<action selector="lowercaseWord:" destination="465" id="468"/>
|
||||
<action selector="makeBaseWritingDirectionLeftToRight:" destination="511" id="526"/>
|
||||
<action selector="makeBaseWritingDirectionNatural:" destination="510" id="525"/>
|
||||
<action selector="makeBaseWritingDirectionRightToLeft:" destination="512" id="527"/>
|
||||
<action selector="makeTextWritingDirectionLeftToRight:" destination="516" id="529"/>
|
||||
<action selector="makeTextWritingDirectionNatural:" destination="515" id="528"/>
|
||||
<action selector="makeTextWritingDirectionRightToLeft:" destination="517" id="530"/>
|
||||
<action selector="newDocument:" destination="82" id="373"/>
|
||||
<action selector="openDocument:" destination="72" id="374"/>
|
||||
<action selector="orderFrontColorPanel:" destination="401" id="433"/>
|
||||
<action selector="orderFrontSubstitutionsPanel:" destination="457" id="458"/>
|
||||
<action selector="paste:" destination="203" id="226"/>
|
||||
<action selector="pasteAsPlainText:" destination="485" id="486"/>
|
||||
<action selector="pasteFont:" destination="404" id="436"/>
|
||||
<action selector="pasteRuler:" destination="507" id="519"/>
|
||||
<action selector="performClose:" destination="73" id="193"/>
|
||||
<action selector="performFindPanelAction:" destination="209" id="241"/>
|
||||
<action selector="performFindPanelAction:" destination="208" id="487"/>
|
||||
<action selector="performFindPanelAction:" destination="213" id="488"/>
|
||||
<action selector="performFindPanelAction:" destination="221" id="489"/>
|
||||
<action selector="performFindPanelAction:" destination="534" id="535"/>
|
||||
<action selector="performMiniaturize:" destination="23" id="37"/>
|
||||
<action selector="performZoom:" destination="239" id="240"/>
|
||||
<action selector="print:" destination="78" id="86"/>
|
||||
<action selector="raiseBaseline:" destination="409" id="426"/>
|
||||
<action selector="redo:" destination="215" id="231"/>
|
||||
<action selector="revertDocumentToSaved:" destination="112" id="364"/>
|
||||
<action selector="runPageLayout:" destination="77" id="87"/>
|
||||
<action selector="runToolbarCustomizationPalette:" destination="298" id="365"/>
|
||||
<action selector="saveDocument:" destination="75" id="362"/>
|
||||
<action selector="selectAll:" destination="198" id="232"/>
|
||||
<action selector="showGuessPanel:" destination="204" id="230"/>
|
||||
<action selector="showHelp:" destination="492" id="493"/>
|
||||
<action selector="startSpeaking:" destination="196" id="233"/>
|
||||
<action selector="stopSpeaking:" destination="195" id="227"/>
|
||||
<action selector="subscript:" destination="408" id="429"/>
|
||||
<action selector="superscript:" destination="407" id="430"/>
|
||||
<action selector="tightenKerning:" destination="418" id="431"/>
|
||||
<action selector="toggleAutomaticDashSubstitution:" destination="460" id="461"/>
|
||||
<action selector="toggleAutomaticLinkDetection:" destination="354" id="357"/>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" destination="351" id="356"/>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" destination="454" id="456"/>
|
||||
<action selector="toggleAutomaticTextReplacement:" destination="462" id="463"/>
|
||||
<action selector="toggleContinuousSpellChecking:" destination="219" id="222"/>
|
||||
<action selector="toggleGrammarChecking:" destination="346" id="347"/>
|
||||
<action selector="toggleRuler:" destination="505" id="520"/>
|
||||
<action selector="toggleSmartInsertDelete:" destination="350" id="355"/>
|
||||
<action selector="toggleToolbarShown:" destination="297" id="366"/>
|
||||
<action selector="turnOffKerning:" destination="417" id="441"/>
|
||||
<action selector="turnOffLigatures:" destination="413" id="440"/>
|
||||
<action selector="underline:" destination="392" id="432"/>
|
||||
<action selector="undo:" destination="207" id="223"/>
|
||||
<action selector="unhideAllApplications:" destination="150" id="370"/>
|
||||
<action selector="unscript:" destination="406" id="437"/>
|
||||
<action selector="uppercaseWord:" destination="452" id="464"/>
|
||||
<action selector="useAllLigatures:" destination="414" id="434"/>
|
||||
<action selector="useStandardKerning:" destination="416" id="438"/>
|
||||
<action selector="useStandardLigatures:" destination="412" id="439"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-3" userLabel="Application">
|
||||
<connections>
|
||||
<action selector="terminate:" destination="136" id="449"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<menu title="AMainMenu" systemMenu="main" id="29">
|
||||
<items>
|
||||
<menuItem title="ExampleAppMac" id="56">
|
||||
@@ -102,6 +19,9 @@
|
||||
<items>
|
||||
<menuItem title="About ExampleAppMac" id="58">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="236">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
@@ -116,95 +36,211 @@
|
||||
<menuItem isSeparatorItem="YES" id="144">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Hide ExampleAppMac" keyEquivalent="h" id="134"/>
|
||||
<menuItem title="Hide ExampleAppMac" keyEquivalent="h" id="134">
|
||||
<connections>
|
||||
<action selector="hide:" target="-1" id="367"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hide Others" keyEquivalent="h" id="145">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hideOtherApplications:" target="-1" id="368"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="150">
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="-1" id="370"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="150"/>
|
||||
<menuItem isSeparatorItem="YES" id="149">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Quit ExampleAppMac" keyEquivalent="q" id="136"/>
|
||||
<menuItem title="Quit ExampleAppMac" keyEquivalent="q" id="136">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-3" id="449"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="83">
|
||||
<menu key="submenu" title="File" id="81">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="82"/>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="72"/>
|
||||
<menuItem title="New" keyEquivalent="n" id="82">
|
||||
<connections>
|
||||
<action selector="newDocument:" target="-1" id="373"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="72">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="-1" id="374"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Recent" id="124">
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="125">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="126"/>
|
||||
<menuItem title="Clear Menu" id="126">
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="-1" id="127"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="79">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Close" keyEquivalent="w" id="73"/>
|
||||
<menuItem title="Save…" keyEquivalent="s" id="75"/>
|
||||
<menuItem title="Close" keyEquivalent="w" id="73">
|
||||
<connections>
|
||||
<action selector="performClose:" target="-1" id="193"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save…" keyEquivalent="s" id="75">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="-1" id="362"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Revert to Saved" id="112">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="revertDocumentToSaved:" target="-1" id="364"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="74">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Page Setup..." keyEquivalent="P" id="77">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="runPageLayout:" target="-1" id="87"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" keyEquivalent="p" id="78">
|
||||
<connections>
|
||||
<action selector="print:" target="-1" id="86"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" keyEquivalent="p" id="78"/>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="217">
|
||||
<menu key="submenu" title="Edit" id="205">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="207"/>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="207">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="223"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="215">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="231"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="206">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="199"/>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="197"/>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="203"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="199">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="228"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="197">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="224"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="203">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="226"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="485">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="-1" id="486"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="202">
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="235"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="198">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="232"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="202"/>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="198"/>
|
||||
<menuItem isSeparatorItem="YES" id="214">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Find" id="218">
|
||||
<menu key="submenu" title="Find" id="220">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="209"/>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="209">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="241"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="534">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="535"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="208">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="487"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="208"/>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="488"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="489"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="210">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="245"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221"/>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="210"/>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="216">
|
||||
<menu key="submenu" title="Spelling and Grammar" id="200">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="204"/>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="201"/>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="204">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="230"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="201">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="225"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="453"/>
|
||||
<menuItem title="Check Spelling While Typing" id="219"/>
|
||||
<menuItem title="Check Grammar With Spelling" id="346"/>
|
||||
<menuItem title="Check Spelling While Typing" id="219">
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="222"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="346">
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="347"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="454">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="456"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
@@ -214,18 +250,38 @@
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="457">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="458"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="459"/>
|
||||
<menuItem title="Smart Copy/Paste" tag="1" keyEquivalent="f" id="350"/>
|
||||
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351"/>
|
||||
<menuItem title="Smart Copy/Paste" tag="1" keyEquivalent="f" id="350">
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="355"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351">
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="356"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="460">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="461"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" tag="3" keyEquivalent="G" id="354">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="357"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="462">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="-1" id="463"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
@@ -236,12 +292,21 @@
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="452">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="-1" id="464"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="465">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="-1" id="468"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="466">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="-1" id="467"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
@@ -249,8 +314,16 @@
|
||||
<menuItem title="Speech" id="211">
|
||||
<menu key="submenu" title="Speech" id="212">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="196"/>
|
||||
<menuItem title="Stop Speaking" id="195"/>
|
||||
<menuItem title="Start Speaking" id="196">
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="233"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="195">
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="227"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
@@ -265,13 +338,37 @@
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Font" systemMenu="font" id="388">
|
||||
<items>
|
||||
<menuItem title="Show Fonts" keyEquivalent="t" id="389"/>
|
||||
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390"/>
|
||||
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391"/>
|
||||
<menuItem title="Underline" keyEquivalent="u" id="392"/>
|
||||
<menuItem title="Show Fonts" keyEquivalent="t" id="389">
|
||||
<connections>
|
||||
<action selector="orderFrontFontPanel:" target="420" id="424"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="420" id="421"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="420" id="422"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Underline" keyEquivalent="u" id="392">
|
||||
<connections>
|
||||
<action selector="underline:" target="-1" id="432"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="393"/>
|
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="394"/>
|
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395"/>
|
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="394">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="420" id="425"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="420" id="423"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="396"/>
|
||||
<menuItem title="Kern" id="397">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
@@ -279,15 +376,27 @@
|
||||
<items>
|
||||
<menuItem title="Use Default" id="416">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardKerning:" target="-1" id="438"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="417">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffKerning:" target="-1" id="441"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Tighten" id="418">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="tightenKerning:" target="-1" id="431"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Loosen" id="419">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="loosenKerning:" target="-1" id="435"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
@@ -298,12 +407,21 @@
|
||||
<items>
|
||||
<menuItem title="Use Default" id="412">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardLigatures:" target="-1" id="439"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="413">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffLigatures:" target="-1" id="440"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use All" id="414">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useAllLigatures:" target="-1" id="434"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
@@ -314,30 +432,55 @@
|
||||
<items>
|
||||
<menuItem title="Use Default" id="406">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unscript:" target="-1" id="437"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Superscript" id="407">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="superscript:" target="-1" id="430"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Subscript" id="408">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="subscript:" target="-1" id="429"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Raise" id="409">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="raiseBaseline:" target="-1" id="426"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Lower" id="410">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowerBaseline:" target="-1" id="427"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="400"/>
|
||||
<menuItem title="Show Colors" keyEquivalent="C" id="401"/>
|
||||
<menuItem title="Show Colors" keyEquivalent="C" id="401">
|
||||
<connections>
|
||||
<action selector="orderFrontColorPanel:" target="-1" id="433"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="402"/>
|
||||
<menuItem title="Copy Style" keyEquivalent="c" id="403">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyFont:" target="-1" id="428"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Style" keyEquivalent="v" id="404">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteFont:" target="-1" id="436"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
@@ -346,12 +489,27 @@
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Text" id="497">
|
||||
<items>
|
||||
<menuItem title="Align Left" keyEquivalent="{" id="498"/>
|
||||
<menuItem title="Center" keyEquivalent="|" id="499"/>
|
||||
<menuItem title="Align Left" keyEquivalent="{" id="498">
|
||||
<connections>
|
||||
<action selector="alignLeft:" target="-1" id="524"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Center" keyEquivalent="|" id="499">
|
||||
<connections>
|
||||
<action selector="alignCenter:" target="-1" id="518"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Justify" id="500">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="alignJustified:" target="-1" id="523"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Align Right" keyEquivalent="}" id="501">
|
||||
<connections>
|
||||
<action selector="alignRight:" target="-1" id="521"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Align Right" keyEquivalent="}" id="501"/>
|
||||
<menuItem isSeparatorItem="YES" id="502"/>
|
||||
<menuItem title="Writing Direction" id="503">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
@@ -363,14 +521,23 @@
|
||||
<menuItem id="510">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="525"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="511">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="526"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="512">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="527"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="513"/>
|
||||
<menuItem title="Selection" enabled="NO" id="514">
|
||||
@@ -379,14 +546,23 @@
|
||||
<menuItem id="515">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionNatural:" target="-1" id="528"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="516">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="529"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="517">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="530"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
@@ -394,12 +570,21 @@
|
||||
<menuItem isSeparatorItem="YES" id="504"/>
|
||||
<menuItem title="Show Ruler" id="505">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleRuler:" target="-1" id="520"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy Ruler" keyEquivalent="c" id="506">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyRuler:" target="-1" id="522"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Ruler" keyEquivalent="v" id="507">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteRuler:" target="-1" id="519"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
@@ -412,20 +597,39 @@
|
||||
<items>
|
||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="297">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleToolbarShown:" target="-1" id="366"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Customize Toolbar…" id="298">
|
||||
<connections>
|
||||
<action selector="runToolbarCustomizationPalette:" target="-1" id="365"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Customize Toolbar…" id="298"/>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="19">
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="24">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="23"/>
|
||||
<menuItem title="Zoom" id="239"/>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="23">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="37"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="239">
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="240"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="92">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Bring All to Front" id="5"/>
|
||||
<menuItem title="Bring All to Front" id="5">
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="39"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
@@ -433,17 +637,21 @@
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Help" systemMenu="help" id="491">
|
||||
<items>
|
||||
<menuItem title="ExampleAppMac Help" keyEquivalent="?" id="492"/>
|
||||
<menuItem title="ExampleAppMac Help" keyEquivalent="?" id="492">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="-1" id="493"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<window title="ExampleAppMac" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="335" y="390" width="480" height="360"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1418"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
|
||||
<view key="contentView" id="372">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
@@ -454,14 +662,6 @@
|
||||
<outlet property="window" destination="371" id="532"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="420" customClass="NSFontManager">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" destination="390" id="421"/>
|
||||
<action selector="addFontTrait:" destination="391" id="422"/>
|
||||
<action selector="modifyFont:" destination="395" id="423"/>
|
||||
<action selector="modifyFont:" destination="394" id="425"/>
|
||||
<action selector="orderFrontFontPanel:" destination="389" id="424"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="420" customClass="NSFontManager"/>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.abstractpath.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.abstractpath.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Inspired by Matt Gallagher's AudioStreamer:
|
||||
https://github.com/mattgallagher/AudioStreamer
|
||||
|
||||
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
|
||||
Copyright (c) 2015 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
@@ -15,12 +15,12 @@
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the <organization>.
|
||||
This product includes software developed by Thong Nguyen.
|
||||
4. Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||
THIS SOFTWARE IS PROVIDED BY THONG NGUYEN ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
|
||||
@@ -11,7 +11,7 @@ The primary motivation of this project was to decouple the input data sources fr
|
||||
* Easy to read source.
|
||||
* Carefully multi-threaded to provide a responsive API that won't block your UI thread nor starve the audio buffers.
|
||||
* Buffered and gapless playback between all format types.
|
||||
* Easy to implement audio data sources (Local, HTTP, AutoRecoveryingHTTP DataSources are provided).
|
||||
* Easy to implement audio data sources (Local, HTTP, AutoRecoveringHTTP DataSources are provided).
|
||||
* Easy to extend DataSource to support adaptive buffering, encryption, etc.
|
||||
* Optimised for low CPU/battery usage (0% - 1% CPU usage when streaming).
|
||||
* Optimised for linear data sources. Random access sources are required only for seeking.
|
||||
@@ -63,4 +63,4 @@ STKAudioPlayer* audioPlayer = [[STKAudioPlayer alloc] init];
|
||||
More documentation is available on the project [Wiki](https://github.com/tumtumtum/StreamingKit/wiki/_pages)
|
||||
|
||||
### Authors and Contributors
|
||||
Copyright (c) 2012-2014, Thong Nguyen ([@tumtumtum](http://www.twitter.com/tumtumtum))
|
||||
Copyright (c) 2012-2019, Thong Nguyen ([@tumtumtum](http://www.twitter.com/tumtumtum))
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "StreamingKit"
|
||||
s.version = "0.0.0"
|
||||
s.summary = "A fast and extensible audio streamer for iOS and OSX with support for gapless playback and custom (non-HTTP) sources."
|
||||
s.homepage = "https://github.com/tumtumtum/StreamingKit/"
|
||||
s.license = 'MIT'
|
||||
s.author = { "Thong Nguyen" => "tumtumtum@gmail.com" }
|
||||
s.source = { :git => "https://github.com/tumtumtum/StreamingKit.git" }
|
||||
s.platform = :ios
|
||||
s.requires_arc = true
|
||||
s.source_files = 'StreamingKit/StreamingKit/*.{h,m}'
|
||||
s.ios.deployment_target = '4.3'
|
||||
s.ios.frameworks = 'SystemConfiguration', 'CFNetwork', 'CoreFoundation', 'AudioToolbox'
|
||||
s.osx.deployment_target = '10.7'
|
||||
s.osx.frameworks = 'SystemConfiguration', 'CFNetwork', 'CoreFoundation', 'AudioToolbox', 'AudioUnit'
|
||||
end
|
||||
@@ -1,16 +1,16 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "StreamingKit"
|
||||
s.version = "0.1.25"
|
||||
s.version = "0.1.31"
|
||||
s.platform = :ios
|
||||
s.ios.deployment_target = '5.0'
|
||||
s.osx.deployment_target = '10.7'
|
||||
s.summary = "A fast and extensible audio streamer for iOS and OSX with support for gapless playback and custom (non-HTTP) sources."
|
||||
s.homepage = "https://github.com/tumtumtum/StreamingKit/"
|
||||
s.license = 'MIT'
|
||||
s.author = { "Thong Nguyen" => "tumtumtum@gmail.com" }
|
||||
s.source = { :git => "https://github.com/tumtumtum/StreamingKit.git", :tag => s.version.to_s}
|
||||
s.platform = :ios
|
||||
s.requires_arc = true
|
||||
s.source_files = 'StreamingKit/StreamingKit/*.{h,m}'
|
||||
s.ios.deployment_target = '4.3'
|
||||
s.ios.frameworks = 'SystemConfiguration', 'CFNetwork', 'CoreFoundation', 'AudioToolbox'
|
||||
s.osx.deployment_target = '10.7'
|
||||
s.osx.frameworks = 'SystemConfiguration', 'CFNetwork', 'CoreFoundation', 'AudioToolbox', 'AudioUnit'
|
||||
end
|
||||
|
||||
@@ -7,6 +7,18 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
40B6239322423B1E005D725D /* STKMacro.h in Headers */ = {isa = PBXBuildFile; fileRef = 40B6239222423B1E005D725D /* STKMacro.h */; };
|
||||
40B6239422423B1F005D725D /* STKMacro.h in Headers */ = {isa = PBXBuildFile; fileRef = 40B6239222423B1E005D725D /* STKMacro.h */; };
|
||||
40B6239822423F28005D725D /* STKSpinLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 40B6239722423F28005D725D /* STKSpinLock.h */; };
|
||||
40B6239922423F28005D725D /* STKSpinLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 40B6239722423F28005D725D /* STKSpinLock.h */; };
|
||||
5B949CD21A1140E4005675A0 /* STKAudioPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7C4F1188D5E550010896F /* STKAudioPlayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
5B949CD31A1140E4005675A0 /* STKAutoRecoveringHTTPDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7C4F3188D5E550010896F /* STKAutoRecoveringHTTPDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
5B949CD41A1140E4005675A0 /* STKCoreFoundationDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7C4F5188D5E550010896F /* STKCoreFoundationDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
5B949CD51A1140E4005675A0 /* STKDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7C4F7188D5E550010896F /* STKDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
5B949CD61A1140E4005675A0 /* STKDataSourceWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7C4F9188D5E550010896F /* STKDataSourceWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
5B949CD71A1140E4005675A0 /* STKHTTPDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7C4FB188D5E550010896F /* STKHTTPDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
5B949CD81A1140E4005675A0 /* STKLocalFileDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7C4FD188D5E550010896F /* STKLocalFileDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
5B949CD91A1140E4005675A0 /* STKQueueEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BF65D0189A6582004DD08C /* STKQueueEntry.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
A1A4996B189E744400E2A2E2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A4996A189E744400E2A2E2 /* Cocoa.framework */; };
|
||||
A1A49975189E744500E2A2E2 /* StreamingKitMac.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A49974189E744500E2A2E2 /* StreamingKitMac.m */; };
|
||||
A1A4997B189E744500E2A2E2 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E7C4D9188D57F60010896F /* XCTest.framework */; };
|
||||
@@ -83,6 +95,8 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
40B6239222423B1E005D725D /* STKMacro.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STKMacro.h; sourceTree = "<group>"; };
|
||||
40B6239722423F28005D725D /* STKSpinLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STKSpinLock.h; sourceTree = "<group>"; };
|
||||
A1A49969189E744400E2A2E2 /* libStreamingKitMac.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libStreamingKitMac.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A1A4996A189E744400E2A2E2 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; };
|
||||
A1A4996D189E744500E2A2E2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
@@ -262,6 +276,8 @@
|
||||
A1E7C4CD188D57F50010896F /* StreamingKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A1BF65D3189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.h */,
|
||||
A1BF65D4189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.m */,
|
||||
A1E7C4F1188D5E550010896F /* STKAudioPlayer.h */,
|
||||
A1E7C4F2188D5E550010896F /* STKAudioPlayer.m */,
|
||||
A1E7C4F3188D5E550010896F /* STKAutoRecoveringHTTPDataSource.h */,
|
||||
@@ -276,10 +292,10 @@
|
||||
A1E7C4FC188D5E550010896F /* STKHTTPDataSource.m */,
|
||||
A1E7C4FD188D5E550010896F /* STKLocalFileDataSource.h */,
|
||||
A1E7C4FE188D5E550010896F /* STKLocalFileDataSource.m */,
|
||||
40B6239222423B1E005D725D /* STKMacro.h */,
|
||||
A1BF65D0189A6582004DD08C /* STKQueueEntry.h */,
|
||||
A1BF65D1189A6582004DD08C /* STKQueueEntry.m */,
|
||||
A1BF65D3189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.h */,
|
||||
A1BF65D4189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.m */,
|
||||
40B6239722423F28005D725D /* STKSpinLock.h */,
|
||||
A1E7C4CE188D57F50010896F /* Supporting Files */,
|
||||
);
|
||||
path = StreamingKit;
|
||||
@@ -314,10 +330,29 @@
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
5B949CD11A1140CF005675A0 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
40B6239822423F28005D725D /* STKSpinLock.h in Headers */,
|
||||
5B949CD21A1140E4005675A0 /* STKAudioPlayer.h in Headers */,
|
||||
5B949CD31A1140E4005675A0 /* STKAutoRecoveringHTTPDataSource.h in Headers */,
|
||||
5B949CD41A1140E4005675A0 /* STKCoreFoundationDataSource.h in Headers */,
|
||||
40B6239322423B1E005D725D /* STKMacro.h in Headers */,
|
||||
5B949CD51A1140E4005675A0 /* STKDataSource.h in Headers */,
|
||||
5B949CD61A1140E4005675A0 /* STKDataSourceWrapper.h in Headers */,
|
||||
5B949CD71A1140E4005675A0 /* STKHTTPDataSource.h in Headers */,
|
||||
5B949CD81A1140E4005675A0 /* STKLocalFileDataSource.h in Headers */,
|
||||
5B949CD91A1140E4005675A0 /* STKQueueEntry.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
A1A49967189E744400E2A2E2 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
40B6239922423F28005D725D /* STKSpinLock.h in Headers */,
|
||||
40B6239422423B1F005D725D /* STKMacro.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -366,6 +401,7 @@
|
||||
A1E7C4C4188D57F50010896F /* Sources */,
|
||||
A1E7C4C5188D57F50010896F /* Frameworks */,
|
||||
A1E7C4C6188D57F50010896F /* CopyFiles */,
|
||||
5B949CD11A1140CF005675A0 /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -401,7 +437,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
CLASSPREFIX = STK;
|
||||
LastUpgradeCheck = 0610;
|
||||
LastUpgradeCheck = 1010;
|
||||
ORGANIZATIONNAME = "Thong Nguyen";
|
||||
};
|
||||
buildConfigurationList = A1E7C4C3188D57F50010896F /* Build configuration list for PBXProject "StreamingKit" */;
|
||||
@@ -568,6 +604,7 @@
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PUBLIC_HEADERS_FOLDER_PATH = include/StreamingKit;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
@@ -586,6 +623,7 @@
|
||||
GCC_PREFIX_HEADER = "StreamingKitMac/StreamingKitMac-Prefix.pch";
|
||||
MACOSX_DEPLOYMENT_TARGET = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PUBLIC_HEADERS_FOLDER_PATH = include/StreamingKit;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
@@ -607,6 +645,7 @@
|
||||
);
|
||||
INFOPLIST_FILE = "StreamingKitMacTests/StreamingKitMacTests-Info.plist";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.abstractpath.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = macosx;
|
||||
WRAPPER_EXTENSION = xctest;
|
||||
@@ -627,6 +666,7 @@
|
||||
GCC_PREFIX_HEADER = "StreamingKitMac/StreamingKitMac-Prefix.pch";
|
||||
INFOPLIST_FILE = "StreamingKitMacTests/StreamingKitMacTests-Info.plist";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.abstractpath.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = macosx;
|
||||
WRAPPER_EXTENSION = xctest;
|
||||
@@ -641,17 +681,31 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
@@ -664,7 +718,8 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
@@ -678,24 +733,38 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
@@ -713,6 +782,7 @@
|
||||
GCC_PREFIX_HEADER = "StreamingKit/StreamingKit-Prefix.pch";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PUBLIC_HEADERS_FOLDER_PATH = include/StreamingKit;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
@@ -729,6 +799,7 @@
|
||||
GCC_PREFIX_HEADER = "StreamingKit/StreamingKit-Prefix.pch";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PUBLIC_HEADERS_FOLDER_PATH = include/StreamingKit;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
@@ -748,6 +819,7 @@
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = "StreamingKitTests/StreamingKitTests-Info.plist";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = xctest;
|
||||
};
|
||||
@@ -764,6 +836,7 @@
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "StreamingKit/StreamingKit-Prefix.pch";
|
||||
INFOPLIST_FILE = "StreamingKitTests/StreamingKitTests-Info.plist";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = xctest;
|
||||
};
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -8,10 +8,14 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NSMutableArray (STKAudioPlayer)
|
||||
-(void) enqueue:(id)obj;
|
||||
-(void) skipQueue:(id)obj;
|
||||
-(void) skipQueueWithQueue:(NSMutableArray*)queue;
|
||||
-(id) dequeue;
|
||||
-(id) peek;
|
||||
-(nullable id) dequeue;
|
||||
-(nullable id) peek;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -44,7 +44,9 @@
|
||||
#include "UIKit/UIApplication.h"
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_OPTIONS(NSInteger, STKAudioPlayerState)
|
||||
{
|
||||
STKAudioPlayerStateReady,
|
||||
STKAudioPlayerStateRunning = 1,
|
||||
@@ -54,10 +56,9 @@ typedef enum
|
||||
STKAudioPlayerStateStopped = (1 << 4),
|
||||
STKAudioPlayerStateError = (1 << 5),
|
||||
STKAudioPlayerStateDisposed = (1 << 6)
|
||||
}
|
||||
STKAudioPlayerState;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
typedef NS_ENUM(NSInteger, STKAudioPlayerStopReason)
|
||||
{
|
||||
STKAudioPlayerStopReasonNone = 0,
|
||||
STKAudioPlayerStopReasonEof,
|
||||
@@ -65,10 +66,9 @@ typedef enum
|
||||
STKAudioPlayerStopReasonPendingNext,
|
||||
STKAudioPlayerStopReasonDisposed,
|
||||
STKAudioPlayerStopReasonError = 0xffff
|
||||
}
|
||||
STKAudioPlayerStopReason;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
typedef NS_ENUM(NSInteger, STKAudioPlayerErrorCode)
|
||||
{
|
||||
STKAudioPlayerErrorNone = 0,
|
||||
STKAudioPlayerErrorDataSource,
|
||||
@@ -77,9 +77,13 @@ typedef enum
|
||||
STKAudioPlayerErrorCodecError,
|
||||
STKAudioPlayerErrorDataNotFound,
|
||||
STKAudioPlayerErrorOther = 0xffff
|
||||
}
|
||||
STKAudioPlayerErrorCode;
|
||||
};
|
||||
|
||||
///
|
||||
/// Options to initiailise the Audioplayer with.
|
||||
/// By default if you set buffer size or seconds to 0, the non-zero default will be used
|
||||
/// If you would like to disable the buffer option completely set to STK_DISABLE_BUFFER
|
||||
///
|
||||
typedef struct
|
||||
{
|
||||
/// If YES then seeking a track will cause all pending items to be flushed from the queue
|
||||
@@ -91,7 +95,7 @@ typedef struct
|
||||
/// The size of the internal I/O read buffer. This data in this buffer is transient and does not need to be larger.
|
||||
UInt32 readBufferSize;
|
||||
/// The size of the decompressed buffer (Default is 10 seconds which uses about 1.7MB of RAM)
|
||||
UInt32 bufferSizeInSeconds;
|
||||
Float32 bufferSizeInSeconds;
|
||||
/// Number of seconds of decompressed audio is required before playback first starts for each item (Default is 0.5 seconds. Must be larger than bufferSizeInSeconds)
|
||||
Float32 secondsRequiredToStartPlaying;
|
||||
/// Seconds after a seek is performed before data needs to come in (after which the state will change to playing/buffering)
|
||||
@@ -101,6 +105,8 @@ typedef struct
|
||||
}
|
||||
STKAudioPlayerOptions;
|
||||
|
||||
#define STK_DISABLE_BUFFER (0xffffffff)
|
||||
|
||||
typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames);
|
||||
|
||||
@interface STKFrameFilterEntry : NSObject
|
||||
@@ -129,6 +135,9 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn
|
||||
/// Raised when items queued items are cleared (usually because of a call to play, setDataSource or stop)
|
||||
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didCancelQueuedItems:(NSArray*)queuedItems;
|
||||
|
||||
/// Raised when datasource read stream metadata. Called from the non-main thread.
|
||||
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didReadStreamMetadata:(NSDictionary*)dictionary;
|
||||
|
||||
@end
|
||||
|
||||
@interface STKAudioPlayer : NSObject<STKDataSourceDelegate>
|
||||
@@ -142,18 +151,22 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn
|
||||
@property (readonly) double duration;
|
||||
/// Gets the current item progress in seconds
|
||||
@property (readonly) double progress;
|
||||
/// Gets or sets the playback rate (default is 1.0)
|
||||
@property(readwrite) float rate;
|
||||
// Gets or sets the playback overlap (default is 8.0)
|
||||
@property(readwrite) float overlap;
|
||||
/// Enables or disables peak and average decibel meteting
|
||||
@property (readwrite) BOOL meteringEnabled;
|
||||
/// Enables or disables the EQ
|
||||
@property (readwrite) BOOL equalizerEnabled;
|
||||
/// Returns an array of STKFrameFilterEntry objects representing the filters currently in use
|
||||
@property (readonly) NSArray* frameFilters;
|
||||
@property (readonly, nullable) NSArray* frameFilters;
|
||||
/// Returns the items pending to be played (includes buffering and upcoming items but does not include the current item)
|
||||
@property (readonly) NSArray* pendingQueue;
|
||||
/// The number of items pending to be played (includes buffering and upcoming items but does not include the current item)
|
||||
@property (readonly) NSUInteger pendingQueueCount;
|
||||
/// Gets the most recently queued item that is still pending to play
|
||||
@property (readonly) NSObject* mostRecentlyQueuedStillPendingItem;
|
||||
@property (readonly, nullable) NSObject* mostRecentlyQueuedStillPendingItem;
|
||||
/// Gets the current state of the player
|
||||
@property (readwrite) STKAudioPlayerState state;
|
||||
/// Gets the options provided to the player on startup
|
||||
@@ -161,7 +174,7 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn
|
||||
/// Gets the reason why the player is stopped (if any)
|
||||
@property (readonly) STKAudioPlayerStopReason stopReason;
|
||||
/// Gets and sets the delegate used for receiving events from the STKAudioPlayer
|
||||
@property (readwrite, unsafe_unretained) id<STKAudioPlayerDelegate> delegate;
|
||||
@property (readwrite, weak) id<STKAudioPlayerDelegate> delegate;
|
||||
|
||||
/// Creates a datasource from a given URL.
|
||||
/// URLs with FILE schemes will return an STKLocalFileDataSource.
|
||||
@@ -169,11 +182,14 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn
|
||||
/// URLs with unrecognised schemes will return nil.
|
||||
+(STKDataSource*) dataSourceFromURL:(NSURL*)url;
|
||||
|
||||
/// Returns canonical audio format used by STKFrameFilter blocks.
|
||||
+(AudioStreamBasicDescription)canonicalAudioStreamBasicDescription;
|
||||
|
||||
/// Initializes a new STKAudioPlayer with the default options
|
||||
-(id) init;
|
||||
-(instancetype) init;
|
||||
|
||||
/// Initializes a new STKAudioPlayer with the given options
|
||||
-(id) initWithOptions:(STKAudioPlayerOptions)optionsIn;
|
||||
-(instancetype) initWithOptions:(STKAudioPlayerOptions)optionsIn;
|
||||
|
||||
/// Plays an item from the given URL string (all pending queued items are removed).
|
||||
/// The NSString is used as the queue item ID
|
||||
@@ -250,7 +266,7 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn
|
||||
|
||||
/// Appends a frame filter with the given name and filter block just after the filter with the given name.
|
||||
/// If the given name is nil, the filter will be inserted at the beginning of the filter change
|
||||
-(void) addFrameFilterWithName:(NSString*)name afterFilterWithName:(NSString*)afterFilterWithName block:(STKFrameFilter)block;
|
||||
-(void) addFrameFilterWithName:(NSString*)name afterFilterWithName:(nullable NSString*)afterFilterWithName block:(STKFrameFilter)block;
|
||||
|
||||
/// Reads the peak power in decibals for the given channel (0 or 1).
|
||||
/// Return values are between -60 (low) and 0 (high).
|
||||
@@ -264,3 +280,5 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn
|
||||
-(void) setGain:(float)gain forEqualizerBand:(int)bandIndex;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
Regular → Executable
+527
-150
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,8 @@
|
||||
#import "STKHTTPDataSource.h"
|
||||
#import "STKDataSourceWrapper.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int watchdogPeriodSeconds;
|
||||
@@ -45,8 +47,10 @@ STKAutoRecoveringHTTPDataSourceOptions;
|
||||
|
||||
@interface STKAutoRecoveringHTTPDataSource : STKDataSourceWrapper
|
||||
|
||||
-(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource;
|
||||
-(instancetype) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource;
|
||||
|
||||
@property (readonly) STKHTTPDataSource* innerDataSource;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -101,38 +101,33 @@ static void PopulateOptionsWithDefault(STKAutoRecoveringHTTPDataSourceOptions* o
|
||||
|
||||
@implementation STKAutoRecoveringHTTPDataSource
|
||||
|
||||
@dynamic innerDataSource;
|
||||
|
||||
-(STKHTTPDataSource*) innerHTTPDataSource
|
||||
{
|
||||
return (STKHTTPDataSource*)self.innerDataSource;
|
||||
}
|
||||
|
||||
-(id) initWithDataSource:(STKDataSource *)innerDataSource
|
||||
-(instancetype) initWithDataSource:(STKDataSource *)innerDataSource
|
||||
{
|
||||
return [self initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource];
|
||||
}
|
||||
|
||||
-(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn
|
||||
-(instancetype) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn
|
||||
{
|
||||
return [self initWithHTTPDataSource:innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions){}];
|
||||
}
|
||||
|
||||
-(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions)optionsIn
|
||||
-(instancetype) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions)optionsIn
|
||||
{
|
||||
if (self = [super initWithDataSource:innerDataSourceIn])
|
||||
{
|
||||
if (self = [super initWithDataSource:innerDataSourceIn]) {
|
||||
self.innerDataSource.delegate = self;
|
||||
|
||||
struct sockaddr_in zeroAddress;
|
||||
|
||||
bzero(&zeroAddress, sizeof(zeroAddress));
|
||||
zeroAddress.sin_len = sizeof(zeroAddress);
|
||||
zeroAddress.sin_family = AF_INET;
|
||||
|
||||
PopulateOptionsWithDefault(&optionsIn);
|
||||
|
||||
self->options = optionsIn;
|
||||
|
||||
reachabilityRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress);
|
||||
NSString* hostname = innerDataSourceIn.url.host;
|
||||
if (hostname.length) {
|
||||
reachabilityRef = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]);
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -140,18 +135,16 @@ static void PopulateOptionsWithDefault(STKAutoRecoveringHTTPDataSourceOptions* o
|
||||
|
||||
-(BOOL) startNotifierOnRunLoop:(NSRunLoop*)runLoop
|
||||
{
|
||||
BOOL retVal = NO;
|
||||
SCNetworkReachabilityContext context = { 0, (__bridge void*)self, NULL, NULL, NULL };
|
||||
|
||||
if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
|
||||
{
|
||||
if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, runLoop.getCFRunLoop, kCFRunLoopDefaultMode))
|
||||
{
|
||||
retVal = YES;
|
||||
if (reachabilityRef) {
|
||||
SCNetworkReachabilityContext context = { 0, (__bridge void*)self, NULL, NULL, NULL };
|
||||
if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) {
|
||||
if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, runLoop.getCFRunLoop, kCFRunLoopDefaultMode))
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(BOOL) registerForEvents:(NSRunLoop*)runLoop
|
||||
@@ -238,6 +231,8 @@ static void PopulateOptionsWithDefault(STKAutoRecoveringHTTPDataSourceOptions* o
|
||||
{
|
||||
SCNetworkReachabilityFlags flags;
|
||||
|
||||
if (! reachabilityRef) return YES; // Assume reachability, if unknown
|
||||
|
||||
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
|
||||
{
|
||||
return ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
#import "STKDataSource.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class STKCoreFoundationDataSource;
|
||||
|
||||
@interface CoreFoundationDataSourceClientInfo : NSObject
|
||||
@@ -62,3 +64,5 @@
|
||||
-(CFStreamStatus) status;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -137,8 +137,6 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
|
||||
{
|
||||
CFReadStreamSetClient(stream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, NULL, NULL);
|
||||
CFReadStreamUnscheduleFromRunLoop(stream, [eventsRunLoop getCFRunLoop], kCFRunLoopCommonModes);
|
||||
|
||||
eventsRunLoop = nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Regular → Executable
+8
-1
@@ -35,12 +35,15 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class STKDataSource;
|
||||
|
||||
@protocol STKDataSourceDelegate<NSObject>
|
||||
-(void) dataSourceDataAvailable:(STKDataSource*)dataSource;
|
||||
-(void) dataSourceErrorOccured:(STKDataSource*)dataSource;
|
||||
-(void) dataSourceEof:(STKDataSource*)dataSource;
|
||||
-(void) dataSource:(STKDataSource*)dataSource didReadStreamMetadata:(NSDictionary*)metadata;
|
||||
@end
|
||||
|
||||
@interface STKDataSource : NSObject
|
||||
@@ -49,7 +52,9 @@
|
||||
@property (readonly) SInt64 position;
|
||||
@property (readonly) SInt64 length;
|
||||
@property (readonly) BOOL hasBytesAvailable;
|
||||
@property (readwrite, unsafe_unretained) id<STKDataSourceDelegate> delegate;
|
||||
@property (nonatomic, readwrite, assign) double durationHint;
|
||||
@property (readwrite, unsafe_unretained, nullable) id<STKDataSourceDelegate> delegate;
|
||||
@property (nonatomic, strong, nullable) NSURL *recordToFileUrl;
|
||||
|
||||
-(BOOL) registerForEvents:(NSRunLoop*)runLoop;
|
||||
-(void) unregisterForEvents;
|
||||
@@ -60,3 +65,5 @@
|
||||
-(AudioFileTypeID) audioFileTypeHint;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -34,10 +34,14 @@
|
||||
|
||||
#import "STKDataSource.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface STKDataSourceWrapper : STKDataSource<STKDataSourceDelegate>
|
||||
|
||||
-(id) initWithDataSource:(STKDataSource*)innerDataSource;
|
||||
-(instancetype) initWithDataSource:(STKDataSource*)innerDataSource;
|
||||
|
||||
@property (readonly) STKDataSource* innerDataSource;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
@implementation STKDataSourceWrapper
|
||||
|
||||
-(id) initWithDataSource:(STKDataSource*)innerDataSourceIn
|
||||
-(instancetype) initWithDataSource:(STKDataSource*)innerDataSourceIn
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
@@ -117,4 +117,9 @@
|
||||
[self.delegate dataSourceEof:self];
|
||||
}
|
||||
|
||||
- (void)dataSource:(STKDataSource *)dataSource didReadStreamMetadata:(NSDictionary *)metadata
|
||||
{
|
||||
[self.delegate dataSource:self didReadStreamMetadata:metadata];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -34,10 +34,12 @@
|
||||
|
||||
#import "STKCoreFoundationDataSource.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class STKHTTPDataSource;
|
||||
|
||||
typedef void(^STKURLBlock)(NSURL* url);
|
||||
typedef NSURL*(^STKURLProvider)();
|
||||
typedef NSURL* _Nonnull (^STKURLProvider)(void);
|
||||
typedef void(^STKAsyncURLProvider)(STKHTTPDataSource* dataSource, BOOL forSeek, STKURLBlock callback);
|
||||
|
||||
@interface STKHTTPDataSource : STKCoreFoundationDataSource
|
||||
@@ -46,11 +48,13 @@ typedef void(^STKAsyncURLProvider)(STKHTTPDataSource* dataSource, BOOL forSeek,
|
||||
@property (readonly) UInt32 httpStatusCode;
|
||||
|
||||
+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)fileExtension;
|
||||
-(id) initWithURL:(NSURL*)url;
|
||||
-(id) initWithURL:(NSURL *)url httpRequestHeaders:(NSDictionary *)httpRequestHeaders;
|
||||
-(id) initWithURLProvider:(STKURLProvider)urlProvider;
|
||||
-(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProvider;
|
||||
-(NSRunLoop*) eventsRunLoop;
|
||||
-(instancetype) initWithURL:(NSURL*)url;
|
||||
-(instancetype) initWithURL:(NSURL*)url httpRequestHeaders:(NSDictionary*)httpRequestHeaders;
|
||||
-(instancetype) initWithURLProvider:(STKURLProvider)urlProvider;
|
||||
-(instancetype) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProvider;
|
||||
-(nullable NSRunLoop*) eventsRunLoop;
|
||||
-(void) reconnect;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
Regular → Executable
+144
-28
@@ -52,6 +52,12 @@
|
||||
BOOL iceHeaderAvailable;
|
||||
BOOL httpHeaderNotAvailable;
|
||||
|
||||
NSMutableData *_metadataData;
|
||||
int _metadataOffset;
|
||||
int _metadataBytesRead;
|
||||
int _metadataStep;
|
||||
int _metadataLength;
|
||||
|
||||
NSURL* currentUrl;
|
||||
STKAsyncURLProvider asyncUrlProvider;
|
||||
NSDictionary* httpHeaders;
|
||||
@@ -64,19 +70,20 @@
|
||||
|
||||
@implementation STKHTTPDataSource
|
||||
|
||||
-(id) initWithURL:(NSURL*)urlIn
|
||||
-(instancetype) initWithURL:(NSURL*)urlIn
|
||||
{
|
||||
currentUrl = urlIn;
|
||||
return [self initWithURLProvider:^NSURL* { return urlIn; }];
|
||||
}
|
||||
|
||||
-(id) initWithURL:(NSURL *)urlIn httpRequestHeaders:(NSDictionary *)httpRequestHeaders
|
||||
-(instancetype) initWithURL:(NSURL *)urlIn httpRequestHeaders:(NSDictionary *)httpRequestHeaders
|
||||
{
|
||||
self = [self initWithURLProvider:^NSURL* { return urlIn; }];
|
||||
self->requestHeaders = httpRequestHeaders;
|
||||
return self;
|
||||
}
|
||||
|
||||
-(id) initWithURLProvider:(STKURLProvider)urlProviderIn
|
||||
-(instancetype) initWithURLProvider:(STKURLProvider)urlProviderIn
|
||||
{
|
||||
urlProviderIn = [urlProviderIn copy];
|
||||
|
||||
@@ -86,7 +93,7 @@
|
||||
}];
|
||||
}
|
||||
|
||||
-(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProviderIn
|
||||
-(instancetype) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProviderIn
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
@@ -311,9 +318,18 @@
|
||||
self->iceHeaderData = nil;
|
||||
}
|
||||
|
||||
// check ICY headers
|
||||
NSString* icyHeaders = [httpHeaders objectForKey:@"Icy-Metaint"] ?: [httpHeaders objectForKey:@"icy-metaint"];
|
||||
if (icyHeaders != nil)
|
||||
{
|
||||
_metadataBytesRead = 0;
|
||||
_metadataStep = [icyHeaders intValue];
|
||||
_metadataOffset = _metadataStep;
|
||||
}
|
||||
|
||||
if (([httpHeaders objectForKey:@"Accept-Ranges"] ?: [httpHeaders objectForKey:@"accept-ranges"]) != nil)
|
||||
{
|
||||
self->supportsSeek = YES;
|
||||
self->supportsSeek = ![[httpHeaders objectForKey:@"Accept-Ranges"] isEqualToString:@"none"];
|
||||
}
|
||||
|
||||
if (self.httpStatusCode == 200)
|
||||
@@ -411,7 +427,7 @@
|
||||
|
||||
eventsRunLoop = savedEventsRunLoop;
|
||||
|
||||
[self seekToOffset:self.position];
|
||||
[self seekToOffset:self->supportsSeek ? self.position : 0];
|
||||
}
|
||||
|
||||
-(void) seekToOffset:(SInt64)offset
|
||||
@@ -443,6 +459,7 @@
|
||||
return [self privateReadIntoBuffer:buffer withSize:size];
|
||||
}
|
||||
|
||||
#pragma mark - Custom buffer reading
|
||||
-(int) privateReadIntoBuffer:(UInt8*)buffer withSize:(int)size
|
||||
{
|
||||
if (size == 0)
|
||||
@@ -466,12 +483,90 @@
|
||||
return count;
|
||||
}
|
||||
|
||||
int read = [super readIntoBuffer:buffer withSize:size];
|
||||
int read;
|
||||
|
||||
// read ICY stream metadata
|
||||
// http://www.smackfu.com/stuff/programming/shoutcast.html
|
||||
//
|
||||
if(_metadataStep > 0)
|
||||
{
|
||||
// read audio stream before next metadata chunk
|
||||
if(_metadataOffset > 0)
|
||||
{
|
||||
read = [super readIntoBuffer:buffer withSize:MIN(_metadataOffset, size)];
|
||||
if(read > 0)
|
||||
_metadataOffset -= read;
|
||||
}
|
||||
// read metadata
|
||||
else
|
||||
{
|
||||
// first we need to read one byte with length
|
||||
if(_metadataLength == 0)
|
||||
{
|
||||
// read only 1 byte
|
||||
UInt8 metadataLengthByte;
|
||||
read = [super readIntoBuffer:&metadataLengthByte withSize:1];
|
||||
|
||||
if(read > 0)
|
||||
{
|
||||
_metadataLength = metadataLengthByte * 16;
|
||||
|
||||
// prepare
|
||||
if(_metadataLength > 0)
|
||||
{
|
||||
_metadataData = [NSMutableData dataWithLength:_metadataLength];
|
||||
_metadataBytesRead = 0;
|
||||
}
|
||||
// reset
|
||||
else
|
||||
{
|
||||
_metadataOffset = _metadataStep;
|
||||
_metadataData = nil;
|
||||
_metadataLength = 0;
|
||||
}
|
||||
|
||||
// return 0, because no audio bytes read
|
||||
relativePosition += read;
|
||||
read = 0;
|
||||
}
|
||||
}
|
||||
// read metadata bytes
|
||||
else
|
||||
{
|
||||
read = [super readIntoBuffer:(_metadataData.mutableBytes + _metadataBytesRead)
|
||||
withSize:_metadataLength - _metadataBytesRead];
|
||||
|
||||
if(read > 0)
|
||||
{
|
||||
_metadataBytesRead += read;
|
||||
|
||||
// done reading, so process it
|
||||
if(_metadataBytesRead == _metadataLength)
|
||||
{
|
||||
if([self.delegate respondsToSelector:@selector(dataSource:didReadStreamMetadata:)])
|
||||
[self.delegate dataSource:self didReadStreamMetadata:[self _processIcyMetadata:_metadataData]];
|
||||
|
||||
// reset
|
||||
_metadataData = nil;
|
||||
_metadataOffset = _metadataStep;
|
||||
_metadataLength = 0;
|
||||
_metadataBytesRead = 0;
|
||||
}
|
||||
|
||||
// return 0, because no audio bytes read
|
||||
relativePosition += read;
|
||||
read = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
read = [super readIntoBuffer:buffer withSize:size];
|
||||
}
|
||||
|
||||
if (read < 0)
|
||||
{
|
||||
return read;
|
||||
}
|
||||
|
||||
relativePosition += read;
|
||||
|
||||
@@ -506,11 +601,11 @@
|
||||
|
||||
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(NULL, (CFStringRef)@"GET", (__bridge CFURLRef)self->currentUrl, kCFHTTPVersion1_1);
|
||||
|
||||
if (seekStart > 0 && supportsSeek)
|
||||
if (self->seekStart > 0 && self->supportsSeek)
|
||||
{
|
||||
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Range"), (__bridge CFStringRef)[NSString stringWithFormat:@"bytes=%lld-", seekStart]);
|
||||
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Range"), (__bridge CFStringRef)[NSString stringWithFormat:@"bytes=%lld-", self->seekStart]);
|
||||
|
||||
discontinuous = YES;
|
||||
self->discontinuous = YES;
|
||||
}
|
||||
|
||||
for (NSString* key in self->requestHeaders)
|
||||
@@ -521,11 +616,11 @@
|
||||
}
|
||||
|
||||
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Accept"), CFSTR("*/*"));
|
||||
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Ice-MetaData"), CFSTR("0"));
|
||||
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Icy-MetaData"), CFSTR("1"));
|
||||
|
||||
stream = CFReadStreamCreateForHTTPRequest(NULL, message);
|
||||
|
||||
if (stream == nil)
|
||||
self->stream = CFReadStreamCreateForHTTPRequest(NULL, message);
|
||||
|
||||
if (self->stream == nil)
|
||||
{
|
||||
CFRelease(message);
|
||||
|
||||
@@ -534,9 +629,9 @@
|
||||
return;
|
||||
}
|
||||
|
||||
CFReadStreamSetProperty(stream, (__bridge CFStringRef)NSStreamNetworkServiceTypeBackground, (__bridge CFStringRef)NSStreamNetworkServiceTypeBackground);
|
||||
CFReadStreamSetProperty(self->stream, (__bridge CFStringRef)NSStreamNetworkServiceTypeBackground, (__bridge CFStringRef)NSStreamNetworkServiceTypeBackground);
|
||||
|
||||
if (!CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue))
|
||||
if (!CFReadStreamSetProperty(self->stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue))
|
||||
{
|
||||
CFRelease(message);
|
||||
|
||||
@@ -547,19 +642,17 @@
|
||||
|
||||
// Proxy support
|
||||
CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
|
||||
CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPProxy, proxySettings);
|
||||
CFReadStreamSetProperty(self->stream, kCFStreamPropertyHTTPProxy, proxySettings);
|
||||
CFRelease(proxySettings);
|
||||
|
||||
// SSL support
|
||||
if ([self->currentUrl.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame)
|
||||
{
|
||||
NSDictionary* sslSettings = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
(NSString*)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel,
|
||||
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
|
||||
[NSNull null], kCFStreamSSLPeerName,
|
||||
nil];
|
||||
|
||||
CFReadStreamSetProperty(stream, kCFStreamPropertySSLSettings, (__bridge CFTypeRef)sslSettings);
|
||||
(NSString*)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel,
|
||||
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
|
||||
nil];
|
||||
CFReadStreamSetProperty(self->stream, kCFStreamPropertySSLSettings, (__bridge CFTypeRef)sslSettings);
|
||||
}
|
||||
|
||||
[self reregisterForEvents];
|
||||
@@ -567,12 +660,12 @@
|
||||
self->httpStatusCode = 0;
|
||||
|
||||
// Open
|
||||
if (!CFReadStreamOpen(stream))
|
||||
if (!CFReadStreamOpen(self->stream))
|
||||
{
|
||||
CFRelease(stream);
|
||||
CFRelease(self->stream);
|
||||
CFRelease(message);
|
||||
|
||||
stream = 0;
|
||||
self->stream = NULL;
|
||||
|
||||
[self errorOccured];
|
||||
|
||||
@@ -605,4 +698,27 @@
|
||||
return self->supportsSeek;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (NSDictionary*)_processIcyMetadata:(NSData*)data
|
||||
{
|
||||
NSMutableDictionary *metadata = [NSMutableDictionary new];
|
||||
NSString *metadataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
NSArray *pairs = [metadataString componentsSeparatedByString:@";"];
|
||||
|
||||
for(NSString *pair in pairs)
|
||||
{
|
||||
NSArray *components = [pair componentsSeparatedByString:@"="];
|
||||
if(components.count < 2)
|
||||
continue;
|
||||
|
||||
NSString *key = components[0];
|
||||
NSString *value = [pair substringWithRange:NSMakeRange(key.length + 2, pair.length - (key.length + 2) - 1)];
|
||||
|
||||
[metadata setValue:value forKey:key];
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -34,10 +34,14 @@
|
||||
|
||||
#import "STKCoreFoundationDataSource.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface STKLocalFileDataSource : STKCoreFoundationDataSource
|
||||
|
||||
+(AudioFileTypeID) audioFileTypeHintFromFileExtension:(NSString*)fileExtension;
|
||||
@property (readonly, copy) NSString* filePath;
|
||||
-(id) initWithFilePath:(NSString*)filePath;
|
||||
-(instancetype) initWithFilePath:(NSString*)filePath;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
@implementation STKLocalFileDataSource
|
||||
@synthesize filePath;
|
||||
|
||||
-(id) initWithFilePath:(NSString*)filePathIn
|
||||
-(instancetype) initWithFilePath:(NSString*)filePathIn
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// STKMacro.h
|
||||
// StreamingKit
|
||||
//
|
||||
// Created by Diego Stamigni on 20/03/2019.
|
||||
// Copyright © 2019 Thong Nguyen. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#import <UIKit/UIKit.h>
|
||||
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) \
|
||||
([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
|
||||
#endif
|
||||
|
||||
#define DEPLOYMENT_TARGET_HIGHER_THAN_10 TARGET_OS_WATCH || \
|
||||
TARGET_OS_TV || \
|
||||
(TARGET_OS_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_10_0) || \
|
||||
(!TARGET_OS_IOS && __MAC_OS_X_VERSION_MIN_ALLOWED >= __MAC_10_12)
|
||||
|
||||
#define BASE_SDK_HIGHER_THAN_10 (TARGET_OS_WATCH || \
|
||||
TARGET_OS_TV || \
|
||||
(TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0) || \
|
||||
(!TARGET_OS_IOS && __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_12))
|
||||
|
||||
#define DEVICE_HIGHER_THAN_10 objc_getClass("NSDimension")
|
||||
Regular → Executable
+9
-4
@@ -7,13 +7,15 @@
|
||||
//
|
||||
|
||||
#import "STKDataSource.h"
|
||||
#import "libkern/OSAtomic.h"
|
||||
#import "STKSpinLock.h"
|
||||
#import "AudioToolbox/AudioToolbox.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface STKQueueEntry : NSObject
|
||||
{
|
||||
@public
|
||||
OSSpinLock spinLock;
|
||||
os_unfair_lock spinLock;
|
||||
|
||||
BOOL parsedHeader;
|
||||
Float64 sampleRate;
|
||||
@@ -28,13 +30,14 @@
|
||||
volatile int processedPacketsCount;
|
||||
volatile int processedPacketsSizeTotal;
|
||||
AudioStreamBasicDescription audioStreamBasicDescription;
|
||||
double durationHint;
|
||||
}
|
||||
|
||||
@property (readonly) UInt64 audioDataLengthInBytes;
|
||||
@property (readwrite, retain) NSObject* queueItemId;
|
||||
@property (readwrite, retain) STKDataSource* dataSource;
|
||||
|
||||
-(id) initWithDataSource:(STKDataSource*)dataSource andQueueItemId:(NSObject*)queueItemId;
|
||||
-(instancetype) initWithDataSource:(STKDataSource*)dataSource andQueueItemId:(NSObject*)queueItemId;
|
||||
|
||||
-(void) reset;
|
||||
-(double) duration;
|
||||
@@ -42,4 +45,6 @@
|
||||
-(double) calculatedBitRate;
|
||||
-(BOOL) isDefinitelyCompatible:(AudioStreamBasicDescription*)basicDescription;
|
||||
|
||||
@end
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
Regular → Executable
+12
-9
@@ -14,15 +14,16 @@
|
||||
|
||||
@implementation STKQueueEntry
|
||||
|
||||
-(id) initWithDataSource:(STKDataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn
|
||||
-(instancetype) initWithDataSource:(STKDataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
self->spinLock = OS_SPINLOCK_INIT;
|
||||
self->spinLock = OS_UNFAIR_LOCK_INIT;
|
||||
|
||||
self.dataSource = dataSourceIn;
|
||||
self.queueItemId = queueItemIdIn;
|
||||
self->lastFrameQueued = -1;
|
||||
self->durationHint = dataSourceIn.durationHint;
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -30,11 +31,11 @@
|
||||
|
||||
-(void) reset
|
||||
{
|
||||
OSSpinLockLock(&self->spinLock);
|
||||
setLock(&self->spinLock);
|
||||
self->framesQueued = 0;
|
||||
self->framesPlayed = 0;
|
||||
self->lastFrameQueued = -1;
|
||||
OSSpinLockUnlock(&self->spinLock);
|
||||
lockUnlock(&self->spinLock);
|
||||
}
|
||||
|
||||
-(double) calculatedBitRate
|
||||
@@ -45,7 +46,7 @@
|
||||
{
|
||||
if (processedPacketsCount > STK_BIT_RATE_ESTIMATION_MIN_PACKETS_PREFERRED || (audioStreamBasicDescription.mBytesPerFrame == 0 && processedPacketsCount > STK_BIT_RATE_ESTIMATION_MIN_PACKETS_MIN))
|
||||
{
|
||||
double averagePacketByteSize = processedPacketsSizeTotal / processedPacketsCount;
|
||||
double averagePacketByteSize = (double)processedPacketsSizeTotal / (double)processedPacketsCount;
|
||||
|
||||
retval = averagePacketByteSize / packetDuration * 8;
|
||||
|
||||
@@ -60,6 +61,8 @@
|
||||
|
||||
-(double) duration
|
||||
{
|
||||
if (durationHint > 0.0) return durationHint;
|
||||
|
||||
if (self->sampleRate <= 0)
|
||||
{
|
||||
return 0;
|
||||
@@ -106,9 +109,9 @@
|
||||
|
||||
-(Float64) progressInFrames
|
||||
{
|
||||
OSSpinLockLock(&self->spinLock);
|
||||
Float64 retval = self->seekTime + self->framesPlayed;
|
||||
OSSpinLockUnlock(&self->spinLock);
|
||||
setLock(&self->spinLock);
|
||||
Float64 retval = (self->seekTime + self->audioStreamBasicDescription.mSampleRate) + self->framesPlayed;
|
||||
lockUnlock(&self->spinLock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -118,4 +121,4 @@
|
||||
return [[self queueItemId] description];
|
||||
}
|
||||
|
||||
@end
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// STKSpinLock.h
|
||||
// StreamingKit
|
||||
//
|
||||
// Created by Diego Stamigni on 20/03/2019.
|
||||
// Copyright © 2019 Thong Nguyen. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#import "STKMacro.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
#if BASE_SDK_HIGHER_THAN_10
|
||||
#import <os/lock.h>
|
||||
#else
|
||||
#define OS_UNFAIR_LOCK_INIT ((os_unfair_lock){0})
|
||||
|
||||
typedef struct _os_unfair_lock_s {
|
||||
uint32_t _os_unfair_lock_opaque;
|
||||
} os_unfair_lock, *os_unfair_lock_t;
|
||||
#endif
|
||||
|
||||
#if !DEPLOYMENT_TARGET_HIGHER_THAN_10
|
||||
#import <libkern/OSAtomic.h>
|
||||
static void (*os_unfair_lock_lock_ptr)(void *lock) = NULL;
|
||||
static void (*os_unfair_lock_unlock_ptr)(void *lock) = NULL;
|
||||
#endif
|
||||
|
||||
static void setLock(os_unfair_lock *lock)
|
||||
{
|
||||
#if DEPLOYMENT_TARGET_HIGHER_THAN_10
|
||||
os_unfair_lock_lock(lock);
|
||||
#else
|
||||
if (DEVICE_HIGHER_THAN_10)
|
||||
{
|
||||
if (os_unfair_lock_lock_ptr == NULL)
|
||||
{
|
||||
os_unfair_lock_lock_ptr = dlsym(dlopen(NULL, RTLD_NOW | RTLD_GLOBAL), "os_unfair_lock_lock");
|
||||
}
|
||||
|
||||
if (os_unfair_lock_lock_ptr != NULL)
|
||||
{
|
||||
os_unfair_lock_lock_ptr(lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
OSSpinLockLock((void *)lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void lockUnlock(os_unfair_lock *lock)
|
||||
{
|
||||
#if DEPLOYMENT_TARGET_HIGHER_THAN_10
|
||||
os_unfair_lock_unlock(lock);
|
||||
#else
|
||||
if (DEVICE_HIGHER_THAN_10)
|
||||
{
|
||||
if (os_unfair_lock_unlock_ptr == NULL)
|
||||
{
|
||||
os_unfair_lock_unlock_ptr = dlsym(dlopen(NULL, RTLD_NOW | RTLD_GLOBAL), "os_unfair_lock_unlock");
|
||||
}
|
||||
|
||||
if (os_unfair_lock_unlock_ptr != NULL)
|
||||
{
|
||||
os_unfair_lock_unlock_ptr(lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
OSSpinLockUnlock((void *)lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.abstractpath.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
Reference in New Issue
Block a user