├── .gitignore
├── .travis.yml
├── Example
├── Podfile
├── Tests
│ ├── Tests-Info.plist
│ ├── Tests-Prefix.pch
│ ├── VOXHistogramLevelsConverterTests.m
│ └── en.lproj
│ │ └── InfoPlist.strings
├── VOXHistogramView.xcodeproj
│ ├── project.pbxproj
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── VOXHistogramView-Example.xcscheme
└── VOXHistogramView
│ ├── Helpers
│ ├── VOXJSONConverter.h
│ ├── VOXJSONConverter.m
│ ├── VOXPlayerWrapper.h
│ └── VOXPlayerWrapper.m
│ ├── LaunchScreen.xib
│ ├── Main.storyboard
│ ├── Resources
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── LaunchImage.launchimage
│ │ │ └── Contents.json
│ ├── levels.json
│ └── pink20silence20.mp3
│ ├── VOXAppDelegate.h
│ ├── VOXAppDelegate.m
│ ├── VOXHistogramView-Info.plist
│ ├── VOXHistogramView-Prefix.pch
│ ├── ViewControllers
│ ├── VOXControlHistogramViewController.h
│ ├── VOXControlHistogramViewController.m
│ ├── VOXSimpleHistogramViewController.h
│ ├── VOXSimpleHistogramViewController.m
│ ├── VOXTableViewController.h
│ └── VOXTableViewController.m
│ ├── en.lproj
│ └── InfoPlist.strings
│ └── main.m
├── Gif
└── demo.gif
├── LICENSE
├── Pod
├── Assets
│ └── .gitkeep
└── Classes
│ ├── .gitkeep
│ ├── Animator
│ ├── VOXHistogramAnimator.h
│ └── VOXHistogramAnimator.m
│ ├── Categories
│ ├── UIView+Autolayout.h
│ └── UIView+Autolayout.m
│ ├── Configurations
│ ├── VOXHistogramRenderingConfiguration.h
│ └── VOXHistogramRenderingConfiguration.m
│ ├── LevelsConverter
│ ├── VOXHistogramLevelsConverter.h
│ └── VOXHistogramLevelsConverter.m
│ ├── ProgressLine
│ ├── VOXProgressLineView.h
│ └── VOXProgressLineView.m
│ ├── Rendering
│ ├── VOXHistogramRenderer.h
│ ├── VOXHistogramRenderer.m
│ ├── VOXHistogramRenderingOperation.h
│ └── VOXHistogramRenderingOperation.m
│ ├── VOXHistogramControlView.h
│ ├── VOXHistogramControlView.m
│ ├── VOXHistogramView.h
│ └── VOXHistogramView.m
├── README.md
├── VOXHistogramView.podspec
└── _Pods.xcodeproj
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 | *.xcworkspace
20 | .DS_Store
21 | .idea/
22 |
23 | #CocoaPods
24 | Pods
25 | Podfile.lock
26 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | before_install:
3 | - brew install xctool
4 | - export LANG=en_US.UTF-8
5 | - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
6 | - gem install cocoapods
7 | - cd Example
8 | - pod install
9 | script:
10 | - xctool test -workspace VOXHistogramView.xcworkspace -scheme VOXHistogramView-Example -sdk iphonesimulator
11 | ONLY_ACTIVE_ARCH=NO
12 | notifications:
13 | email:
14 | recipients:
15 | - hawk.ukr@gmail.com
16 | on_success: change
17 | on_failure: always
18 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '7.1'
2 |
3 | source 'https://github.com/CocoaPods/Specs.git'
4 |
5 | inhibit_all_warnings!
6 | #use_frameworks!
7 |
8 | target 'VOXHistogramView_Example', :exclusive => true do
9 | pod "VOXHistogramView", :path => "../"
10 | pod 'APAudioPlayer'
11 | pod 'macros_blocks'
12 | pod 'FrameAccessor'
13 | end
14 |
15 | target 'VOXHistogramView_Tests', :exclusive => true do
16 | pod "VOXHistogramView", :path => "../"
17 | pod 'Expecta'
18 | pod 'OCMock'
19 | end
20 |
--------------------------------------------------------------------------------
/Example/Tests/Tests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Example/Tests/Tests-Prefix.pch:
--------------------------------------------------------------------------------
1 | // The contents of this file are implicitly included at the beginning of every test case source file.
2 |
3 | #ifdef __OBJC__
4 |
5 |
6 |
7 | #endif
8 |
--------------------------------------------------------------------------------
/Example/Tests/VOXHistogramLevelsConverterTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
3 | //
4 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
5 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
6 | // Contact phone: +1 (888) 765-7069
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import
27 | #import "VOXHistogramLevelsConverter.h"
28 | #import "Expecta.h"
29 |
30 |
31 | @interface VOXHistogramLevelsConverterTests : XCTestCase
32 |
33 |
34 | #pragma mark - SUT
35 | @property(nonatomic, strong) VOXHistogramLevelsConverter *converter;
36 | @end
37 |
38 |
39 |
40 | @implementation VOXHistogramLevelsConverterTests
41 |
42 |
43 | - (void)setUp
44 | {
45 | [super setUp];
46 |
47 | self.converter = [VOXHistogramLevelsConverter new];
48 |
49 | NSArray *levels = [self buildLevelsForTesting];
50 | [self.converter updateLevels:levels];
51 | }
52 |
53 | - (void)tearDown
54 | {
55 | self.converter = nil;
56 | [super tearDown];
57 | }
58 |
59 | #pragma mark - Update levels
60 |
61 | - (void)testUpdateLevels
62 | {
63 | expect(self.converter.levels).to.haveCountOf(15);
64 |
65 | [self.converter updateLevels:nil];
66 | expect(self.converter.levels).to.beNil();
67 | }
68 |
69 | #pragma mark - Calculate Levels
70 |
71 | - (void)testCalculateLevelsForSamplingRate_ShouldRaiseExceptionIfSamplingMoreThanLevelsCount
72 | {
73 | expect(^{
74 | [self.converter calculateLevelsForSamplingRate:20 completion:nil];
75 | }).to.raiseAny();
76 | }
77 |
78 | - (void)testCalculateLevelsForSamplingRate_3_Samples
79 | {
80 | [self runAsyncCalculateLevelsForSamplingRate:3 withExpectationsBlock:^(NSArray *levels) {
81 | expect(levels).to.haveCountOf(3);
82 | expect(levels[0]).to.beCloseTo(@0.36666666666667);
83 | expect(levels[1]).to.equal(@0.0);
84 | expect(levels[2]).to.equal(@0.8);
85 | }];
86 | }
87 |
88 | - (void)testCalculateLevelsForSamplingRate_5_Samples
89 | {
90 | [self runAsyncCalculateLevelsForSamplingRate:5 withExpectationsBlock:^(NSArray *levels) {
91 | expect(levels).to.haveCountOf(5);
92 | expect(levels[0]).to.beCloseTo(@0.43333333333333);
93 | expect(levels[1]).to.beCloseTo(@0.26666666666667);
94 | expect(levels[2]).to.equal(@0.0);
95 | expect(levels[3]).to.beCloseTo(@0.86666666666667);
96 | expect(levels[4]).to.beCloseTo(@0.56666666666667);
97 | }];
98 | }
99 |
100 | - (void)testCalculateLevelsForSamplingRate_8_Samples
101 | {
102 | [self runAsyncCalculateLevelsForSamplingRate:8 withExpectationsBlock:^(NSArray *levels) {
103 | expect(levels).to.haveCountOf(8);
104 | expect(levels[0]).to.equal(@0.6);
105 | }];
106 | }
107 |
108 | #pragma mark - Helpers
109 |
110 | - (void)runAsyncCalculateLevelsForSamplingRate:(NSUInteger)samplingRate withExpectationsBlock:(void (^)(NSArray *levels))expectationsBlock
111 | {
112 | XCTestExpectation *expectation = [self expectationWithDescription:nil];
113 | [self.converter calculateLevelsForSamplingRate:samplingRate completion:^(NSArray *levels) {
114 | expectationsBlock(levels);
115 | [expectation fulfill];
116 | }];
117 |
118 | [self waitForExpectationsWithTimeout:3.0 handler:^(NSError *error) {
119 | if (error) {
120 | XCTFail(@"testCalculateLevelsForSamplingRate failed: %@", error);
121 | }
122 | }];
123 | }
124 |
125 | - (NSArray *)buildLevelsForTesting
126 | {
127 | return @[
128 | @0.5, @0.7, @0.1, @0.3, @0.5,
129 | @0.0, @0.0, @0.0, @0.0, @1.0,
130 | @0.8, @0.8, @0.8, @0.8, @0.1
131 | ];
132 | }
133 | @end
134 |
--------------------------------------------------------------------------------
/Example/Tests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
11 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; };
12 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
13 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; };
14 | 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; };
15 | 6003F59E195388D20070C39A /* VOXAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* VOXAppDelegate.m */; };
16 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; };
17 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
18 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
19 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; };
20 | 71697E8D1B3ED39A00A7EB6E /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 71697E8C1B3ED39A00A7EB6E /* LaunchScreen.xib */; };
21 | 71FB0FDD1B3EC2D40034461C /* VOXJSONConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 71FB0FCE1B3EC2D40034461C /* VOXJSONConverter.m */; };
22 | 71FB0FDE1B3EC2D40034461C /* VOXPlayerWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 71FB0FD01B3EC2D40034461C /* VOXPlayerWrapper.m */; };
23 | 71FB0FDF1B3EC2D40034461C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 71FB0FD21B3EC2D40034461C /* Images.xcassets */; };
24 | 71FB0FE01B3EC2D40034461C /* levels.json in Resources */ = {isa = PBXBuildFile; fileRef = 71FB0FD31B3EC2D40034461C /* levels.json */; };
25 | 71FB0FE11B3EC2D40034461C /* pink20silence20.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 71FB0FD41B3EC2D40034461C /* pink20silence20.mp3 */; };
26 | 71FB0FE21B3EC2D40034461C /* VOXControlHistogramViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 71FB0FD71B3EC2D40034461C /* VOXControlHistogramViewController.m */; };
27 | 71FB0FE31B3EC2D40034461C /* VOXSimpleHistogramViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 71FB0FD91B3EC2D40034461C /* VOXSimpleHistogramViewController.m */; };
28 | 71FB0FE41B3EC2D40034461C /* VOXTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 71FB0FDB1B3EC2D40034461C /* VOXTableViewController.m */; };
29 | 71FB0FE61B3EC3820034461C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71FB0FE51B3EC3820034461C /* Main.storyboard */; };
30 | 8A66A2DED9E15CD279668F3F /* libPods-VOXHistogramView_Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 94E7E76625358F6D7325A7D7 /* libPods-VOXHistogramView_Tests.a */; };
31 | B65537312F6A0C928EB5209C /* VOXHistogramLevelsConverterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B655328032E130111FDADB72 /* VOXHistogramLevelsConverterTests.m */; };
32 | D6BDD3282FB05B2F15221A59 /* libPods-VOXHistogramView_Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AC04319ED8CB0971952728EB /* libPods-VOXHistogramView_Example.a */; };
33 | /* End PBXBuildFile section */
34 |
35 | /* Begin PBXContainerItemProxy section */
36 | 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = {
37 | isa = PBXContainerItemProxy;
38 | containerPortal = 6003F582195388D10070C39A /* Project object */;
39 | proxyType = 1;
40 | remoteGlobalIDString = 6003F589195388D20070C39A;
41 | remoteInfo = VOXHistogramView;
42 | };
43 | /* End PBXContainerItemProxy section */
44 |
45 | /* Begin PBXFileReference section */
46 | 01213C494C6660BCE86E1EC1 /* Pods-VOXHistogramView_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VOXHistogramView_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-VOXHistogramView_Tests/Pods-VOXHistogramView_Tests.debug.xcconfig"; sourceTree = ""; };
47 | 0E44244D22C6636AD5F992F4 /* Pods-VOXHistogramView_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VOXHistogramView_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-VOXHistogramView_Example/Pods-VOXHistogramView_Example.debug.xcconfig"; sourceTree = ""; };
48 | 102F05100418733F2372E3E8 /* Pods-VOXHistogramView_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VOXHistogramView_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-VOXHistogramView_Example/Pods-VOXHistogramView_Example.release.xcconfig"; sourceTree = ""; };
49 | 1251BD4B2C95038EE0689182 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; };
50 | 2BD9DA32433F31C658014600 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; };
51 | 31A0AA72121C062F8D8B520C /* VOXHistogramView.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = VOXHistogramView.podspec; path = ../VOXHistogramView.podspec; sourceTree = ""; };
52 | 6003F58A195388D20070C39A /* VOXHistogramView_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VOXHistogramView_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
53 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
54 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
55 | 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
56 | 6003F595195388D20070C39A /* VOXHistogramView-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "VOXHistogramView-Info.plist"; sourceTree = ""; };
57 | 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
58 | 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
59 | 6003F59B195388D20070C39A /* VOXHistogramView-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VOXHistogramView-Prefix.pch"; sourceTree = ""; };
60 | 6003F59C195388D20070C39A /* VOXAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VOXAppDelegate.h; sourceTree = ""; };
61 | 6003F59D195388D20070C39A /* VOXAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VOXAppDelegate.m; sourceTree = ""; };
62 | 6003F5AE195388D20070C39A /* VOXHistogramView_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VOXHistogramView_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
63 | 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
64 | 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; };
65 | 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
66 | 6004BC293FA95C142DA4FEB6 /* Pods-VOXHistogramView_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VOXHistogramView_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-VOXHistogramView_Tests/Pods-VOXHistogramView_Tests.release.xcconfig"; sourceTree = ""; };
67 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; };
68 | 71697E8C1B3ED39A00A7EB6E /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = ""; };
69 | 71FB0FCD1B3EC2D40034461C /* VOXJSONConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VOXJSONConverter.h; sourceTree = ""; };
70 | 71FB0FCE1B3EC2D40034461C /* VOXJSONConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VOXJSONConverter.m; sourceTree = ""; };
71 | 71FB0FCF1B3EC2D40034461C /* VOXPlayerWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VOXPlayerWrapper.h; sourceTree = ""; };
72 | 71FB0FD01B3EC2D40034461C /* VOXPlayerWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VOXPlayerWrapper.m; sourceTree = ""; };
73 | 71FB0FD21B3EC2D40034461C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
74 | 71FB0FD31B3EC2D40034461C /* levels.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = levels.json; sourceTree = ""; };
75 | 71FB0FD41B3EC2D40034461C /* pink20silence20.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = pink20silence20.mp3; sourceTree = ""; };
76 | 71FB0FD61B3EC2D40034461C /* VOXControlHistogramViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VOXControlHistogramViewController.h; sourceTree = ""; };
77 | 71FB0FD71B3EC2D40034461C /* VOXControlHistogramViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VOXControlHistogramViewController.m; sourceTree = ""; };
78 | 71FB0FD81B3EC2D40034461C /* VOXSimpleHistogramViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VOXSimpleHistogramViewController.h; sourceTree = ""; };
79 | 71FB0FD91B3EC2D40034461C /* VOXSimpleHistogramViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VOXSimpleHistogramViewController.m; sourceTree = ""; };
80 | 71FB0FDA1B3EC2D40034461C /* VOXTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VOXTableViewController.h; sourceTree = ""; };
81 | 71FB0FDB1B3EC2D40034461C /* VOXTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VOXTableViewController.m; sourceTree = ""; };
82 | 71FB0FE51B3EC3820034461C /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
83 | 94E7E76625358F6D7325A7D7 /* libPods-VOXHistogramView_Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-VOXHistogramView_Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
84 | AC04319ED8CB0971952728EB /* libPods-VOXHistogramView_Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-VOXHistogramView_Example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
85 | B655328032E130111FDADB72 /* VOXHistogramLevelsConverterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VOXHistogramLevelsConverterTests.m; sourceTree = ""; };
86 | /* End PBXFileReference section */
87 |
88 | /* Begin PBXFrameworksBuildPhase section */
89 | 6003F587195388D20070C39A /* Frameworks */ = {
90 | isa = PBXFrameworksBuildPhase;
91 | buildActionMask = 2147483647;
92 | files = (
93 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */,
94 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */,
95 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */,
96 | D6BDD3282FB05B2F15221A59 /* libPods-VOXHistogramView_Example.a in Frameworks */,
97 | );
98 | runOnlyForDeploymentPostprocessing = 0;
99 | };
100 | 6003F5AB195388D20070C39A /* Frameworks */ = {
101 | isa = PBXFrameworksBuildPhase;
102 | buildActionMask = 2147483647;
103 | files = (
104 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */,
105 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */,
106 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */,
107 | 8A66A2DED9E15CD279668F3F /* libPods-VOXHistogramView_Tests.a in Frameworks */,
108 | );
109 | runOnlyForDeploymentPostprocessing = 0;
110 | };
111 | /* End PBXFrameworksBuildPhase section */
112 |
113 | /* Begin PBXGroup section */
114 | 59884C268B78AE84C894B56D /* Pods */ = {
115 | isa = PBXGroup;
116 | children = (
117 | 0E44244D22C6636AD5F992F4 /* Pods-VOXHistogramView_Example.debug.xcconfig */,
118 | 102F05100418733F2372E3E8 /* Pods-VOXHistogramView_Example.release.xcconfig */,
119 | 01213C494C6660BCE86E1EC1 /* Pods-VOXHistogramView_Tests.debug.xcconfig */,
120 | 6004BC293FA95C142DA4FEB6 /* Pods-VOXHistogramView_Tests.release.xcconfig */,
121 | );
122 | name = Pods;
123 | sourceTree = "";
124 | };
125 | 6003F581195388D10070C39A = {
126 | isa = PBXGroup;
127 | children = (
128 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */,
129 | 6003F593195388D20070C39A /* Example for VOXHistogramView */,
130 | 6003F5B5195388D20070C39A /* Tests */,
131 | 6003F58C195388D20070C39A /* Frameworks */,
132 | 6003F58B195388D20070C39A /* Products */,
133 | 59884C268B78AE84C894B56D /* Pods */,
134 | );
135 | sourceTree = "";
136 | };
137 | 6003F58B195388D20070C39A /* Products */ = {
138 | isa = PBXGroup;
139 | children = (
140 | 6003F58A195388D20070C39A /* VOXHistogramView_Example.app */,
141 | 6003F5AE195388D20070C39A /* VOXHistogramView_Tests.xctest */,
142 | );
143 | name = Products;
144 | sourceTree = "";
145 | };
146 | 6003F58C195388D20070C39A /* Frameworks */ = {
147 | isa = PBXGroup;
148 | children = (
149 | 6003F58D195388D20070C39A /* Foundation.framework */,
150 | 6003F58F195388D20070C39A /* CoreGraphics.framework */,
151 | 6003F591195388D20070C39A /* UIKit.framework */,
152 | 6003F5AF195388D20070C39A /* XCTest.framework */,
153 | AC04319ED8CB0971952728EB /* libPods-VOXHistogramView_Example.a */,
154 | 94E7E76625358F6D7325A7D7 /* libPods-VOXHistogramView_Tests.a */,
155 | );
156 | name = Frameworks;
157 | sourceTree = "";
158 | };
159 | 6003F593195388D20070C39A /* Example for VOXHistogramView */ = {
160 | isa = PBXGroup;
161 | children = (
162 | 71FB0FCC1B3EC2D40034461C /* Helpers */,
163 | 71FB0FD11B3EC2D40034461C /* Resources */,
164 | 71FB0FD51B3EC2D40034461C /* ViewControllers */,
165 | 6003F594195388D20070C39A /* Supporting Files */,
166 | 71FB0FE51B3EC3820034461C /* Main.storyboard */,
167 | 71697E8C1B3ED39A00A7EB6E /* LaunchScreen.xib */,
168 | 6003F59C195388D20070C39A /* VOXAppDelegate.h */,
169 | 6003F59D195388D20070C39A /* VOXAppDelegate.m */,
170 | );
171 | name = "Example for VOXHistogramView";
172 | path = VOXHistogramView;
173 | sourceTree = "";
174 | };
175 | 6003F594195388D20070C39A /* Supporting Files */ = {
176 | isa = PBXGroup;
177 | children = (
178 | 6003F595195388D20070C39A /* VOXHistogramView-Info.plist */,
179 | 6003F596195388D20070C39A /* InfoPlist.strings */,
180 | 6003F599195388D20070C39A /* main.m */,
181 | 6003F59B195388D20070C39A /* VOXHistogramView-Prefix.pch */,
182 | );
183 | name = "Supporting Files";
184 | sourceTree = "";
185 | };
186 | 6003F5B5195388D20070C39A /* Tests */ = {
187 | isa = PBXGroup;
188 | children = (
189 | 6003F5B6195388D20070C39A /* Supporting Files */,
190 | B655328032E130111FDADB72 /* VOXHistogramLevelsConverterTests.m */,
191 | );
192 | path = Tests;
193 | sourceTree = "";
194 | };
195 | 6003F5B6195388D20070C39A /* Supporting Files */ = {
196 | isa = PBXGroup;
197 | children = (
198 | 6003F5B7195388D20070C39A /* Tests-Info.plist */,
199 | 6003F5B8195388D20070C39A /* InfoPlist.strings */,
200 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */,
201 | );
202 | name = "Supporting Files";
203 | sourceTree = "";
204 | };
205 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = {
206 | isa = PBXGroup;
207 | children = (
208 | 31A0AA72121C062F8D8B520C /* VOXHistogramView.podspec */,
209 | 2BD9DA32433F31C658014600 /* README.md */,
210 | 1251BD4B2C95038EE0689182 /* LICENSE */,
211 | );
212 | name = "Podspec Metadata";
213 | sourceTree = "";
214 | };
215 | 71FB0FCC1B3EC2D40034461C /* Helpers */ = {
216 | isa = PBXGroup;
217 | children = (
218 | 71FB0FCD1B3EC2D40034461C /* VOXJSONConverter.h */,
219 | 71FB0FCE1B3EC2D40034461C /* VOXJSONConverter.m */,
220 | 71FB0FCF1B3EC2D40034461C /* VOXPlayerWrapper.h */,
221 | 71FB0FD01B3EC2D40034461C /* VOXPlayerWrapper.m */,
222 | );
223 | path = Helpers;
224 | sourceTree = "";
225 | };
226 | 71FB0FD11B3EC2D40034461C /* Resources */ = {
227 | isa = PBXGroup;
228 | children = (
229 | 71FB0FD21B3EC2D40034461C /* Images.xcassets */,
230 | 71FB0FD31B3EC2D40034461C /* levels.json */,
231 | 71FB0FD41B3EC2D40034461C /* pink20silence20.mp3 */,
232 | );
233 | path = Resources;
234 | sourceTree = "";
235 | };
236 | 71FB0FD51B3EC2D40034461C /* ViewControllers */ = {
237 | isa = PBXGroup;
238 | children = (
239 | 71FB0FD61B3EC2D40034461C /* VOXControlHistogramViewController.h */,
240 | 71FB0FD71B3EC2D40034461C /* VOXControlHistogramViewController.m */,
241 | 71FB0FD81B3EC2D40034461C /* VOXSimpleHistogramViewController.h */,
242 | 71FB0FD91B3EC2D40034461C /* VOXSimpleHistogramViewController.m */,
243 | 71FB0FDA1B3EC2D40034461C /* VOXTableViewController.h */,
244 | 71FB0FDB1B3EC2D40034461C /* VOXTableViewController.m */,
245 | );
246 | path = ViewControllers;
247 | sourceTree = "";
248 | };
249 | /* End PBXGroup section */
250 |
251 | /* Begin PBXNativeTarget section */
252 | 6003F589195388D20070C39A /* VOXHistogramView_Example */ = {
253 | isa = PBXNativeTarget;
254 | buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "VOXHistogramView_Example" */;
255 | buildPhases = (
256 | 138C61765CA9ECE5A02AA85E /* Check Pods Manifest.lock */,
257 | 6003F586195388D20070C39A /* Sources */,
258 | 6003F587195388D20070C39A /* Frameworks */,
259 | 6003F588195388D20070C39A /* Resources */,
260 | 24EEDC0547604F48C3DADBB6 /* Copy Pods Resources */,
261 | );
262 | buildRules = (
263 | );
264 | dependencies = (
265 | );
266 | name = VOXHistogramView_Example;
267 | productName = VOXHistogramView;
268 | productReference = 6003F58A195388D20070C39A /* VOXHistogramView_Example.app */;
269 | productType = "com.apple.product-type.application";
270 | };
271 | 6003F5AD195388D20070C39A /* VOXHistogramView_Tests */ = {
272 | isa = PBXNativeTarget;
273 | buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "VOXHistogramView_Tests" */;
274 | buildPhases = (
275 | EC09068E82E99B232C02F6AB /* Check Pods Manifest.lock */,
276 | 6003F5AA195388D20070C39A /* Sources */,
277 | 6003F5AB195388D20070C39A /* Frameworks */,
278 | 6003F5AC195388D20070C39A /* Resources */,
279 | 2CC4DB15140E50BBB7815131 /* Copy Pods Resources */,
280 | );
281 | buildRules = (
282 | );
283 | dependencies = (
284 | 6003F5B4195388D20070C39A /* PBXTargetDependency */,
285 | );
286 | name = VOXHistogramView_Tests;
287 | productName = VOXHistogramViewTests;
288 | productReference = 6003F5AE195388D20070C39A /* VOXHistogramView_Tests.xctest */;
289 | productType = "com.apple.product-type.bundle.unit-test";
290 | };
291 | /* End PBXNativeTarget section */
292 |
293 | /* Begin PBXProject section */
294 | 6003F582195388D10070C39A /* Project object */ = {
295 | isa = PBXProject;
296 | attributes = {
297 | CLASSPREFIX = VOX;
298 | LastUpgradeCheck = 0510;
299 | ORGANIZATIONNAME = "Nickolay Sheika";
300 | TargetAttributes = {
301 | 6003F5AD195388D20070C39A = {
302 | TestTargetID = 6003F589195388D20070C39A;
303 | };
304 | };
305 | };
306 | buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "VOXHistogramView" */;
307 | compatibilityVersion = "Xcode 3.2";
308 | developmentRegion = English;
309 | hasScannedForEncodings = 0;
310 | knownRegions = (
311 | en,
312 | Base,
313 | );
314 | mainGroup = 6003F581195388D10070C39A;
315 | productRefGroup = 6003F58B195388D20070C39A /* Products */;
316 | projectDirPath = "";
317 | projectRoot = "";
318 | targets = (
319 | 6003F589195388D20070C39A /* VOXHistogramView_Example */,
320 | 6003F5AD195388D20070C39A /* VOXHistogramView_Tests */,
321 | );
322 | };
323 | /* End PBXProject section */
324 |
325 | /* Begin PBXResourcesBuildPhase section */
326 | 6003F588195388D20070C39A /* Resources */ = {
327 | isa = PBXResourcesBuildPhase;
328 | buildActionMask = 2147483647;
329 | files = (
330 | 71FB0FE01B3EC2D40034461C /* levels.json in Resources */,
331 | 71FB0FDF1B3EC2D40034461C /* Images.xcassets in Resources */,
332 | 71FB0FE61B3EC3820034461C /* Main.storyboard in Resources */,
333 | 71FB0FE11B3EC2D40034461C /* pink20silence20.mp3 in Resources */,
334 | 71697E8D1B3ED39A00A7EB6E /* LaunchScreen.xib in Resources */,
335 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */,
336 | );
337 | runOnlyForDeploymentPostprocessing = 0;
338 | };
339 | 6003F5AC195388D20070C39A /* Resources */ = {
340 | isa = PBXResourcesBuildPhase;
341 | buildActionMask = 2147483647;
342 | files = (
343 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */,
344 | );
345 | runOnlyForDeploymentPostprocessing = 0;
346 | };
347 | /* End PBXResourcesBuildPhase section */
348 |
349 | /* Begin PBXShellScriptBuildPhase section */
350 | 138C61765CA9ECE5A02AA85E /* Check Pods Manifest.lock */ = {
351 | isa = PBXShellScriptBuildPhase;
352 | buildActionMask = 2147483647;
353 | files = (
354 | );
355 | inputPaths = (
356 | );
357 | name = "Check Pods Manifest.lock";
358 | outputPaths = (
359 | );
360 | runOnlyForDeploymentPostprocessing = 0;
361 | shellPath = /bin/sh;
362 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
363 | showEnvVarsInLog = 0;
364 | };
365 | 24EEDC0547604F48C3DADBB6 /* Copy Pods Resources */ = {
366 | isa = PBXShellScriptBuildPhase;
367 | buildActionMask = 2147483647;
368 | files = (
369 | );
370 | inputPaths = (
371 | );
372 | name = "Copy Pods Resources";
373 | outputPaths = (
374 | );
375 | runOnlyForDeploymentPostprocessing = 0;
376 | shellPath = /bin/sh;
377 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-VOXHistogramView_Example/Pods-VOXHistogramView_Example-resources.sh\"\n";
378 | showEnvVarsInLog = 0;
379 | };
380 | 2CC4DB15140E50BBB7815131 /* Copy Pods Resources */ = {
381 | isa = PBXShellScriptBuildPhase;
382 | buildActionMask = 2147483647;
383 | files = (
384 | );
385 | inputPaths = (
386 | );
387 | name = "Copy Pods Resources";
388 | outputPaths = (
389 | );
390 | runOnlyForDeploymentPostprocessing = 0;
391 | shellPath = /bin/sh;
392 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-VOXHistogramView_Tests/Pods-VOXHistogramView_Tests-resources.sh\"\n";
393 | showEnvVarsInLog = 0;
394 | };
395 | EC09068E82E99B232C02F6AB /* Check Pods Manifest.lock */ = {
396 | isa = PBXShellScriptBuildPhase;
397 | buildActionMask = 2147483647;
398 | files = (
399 | );
400 | inputPaths = (
401 | );
402 | name = "Check Pods Manifest.lock";
403 | outputPaths = (
404 | );
405 | runOnlyForDeploymentPostprocessing = 0;
406 | shellPath = /bin/sh;
407 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
408 | showEnvVarsInLog = 0;
409 | };
410 | /* End PBXShellScriptBuildPhase section */
411 |
412 | /* Begin PBXSourcesBuildPhase section */
413 | 6003F586195388D20070C39A /* Sources */ = {
414 | isa = PBXSourcesBuildPhase;
415 | buildActionMask = 2147483647;
416 | files = (
417 | 71FB0FDE1B3EC2D40034461C /* VOXPlayerWrapper.m in Sources */,
418 | 71FB0FDD1B3EC2D40034461C /* VOXJSONConverter.m in Sources */,
419 | 6003F59E195388D20070C39A /* VOXAppDelegate.m in Sources */,
420 | 71FB0FE41B3EC2D40034461C /* VOXTableViewController.m in Sources */,
421 | 71FB0FE31B3EC2D40034461C /* VOXSimpleHistogramViewController.m in Sources */,
422 | 6003F59A195388D20070C39A /* main.m in Sources */,
423 | 71FB0FE21B3EC2D40034461C /* VOXControlHistogramViewController.m in Sources */,
424 | );
425 | runOnlyForDeploymentPostprocessing = 0;
426 | };
427 | 6003F5AA195388D20070C39A /* Sources */ = {
428 | isa = PBXSourcesBuildPhase;
429 | buildActionMask = 2147483647;
430 | files = (
431 | B65537312F6A0C928EB5209C /* VOXHistogramLevelsConverterTests.m in Sources */,
432 | );
433 | runOnlyForDeploymentPostprocessing = 0;
434 | };
435 | /* End PBXSourcesBuildPhase section */
436 |
437 | /* Begin PBXTargetDependency section */
438 | 6003F5B4195388D20070C39A /* PBXTargetDependency */ = {
439 | isa = PBXTargetDependency;
440 | target = 6003F589195388D20070C39A /* VOXHistogramView_Example */;
441 | targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */;
442 | };
443 | /* End PBXTargetDependency section */
444 |
445 | /* Begin PBXVariantGroup section */
446 | 6003F596195388D20070C39A /* InfoPlist.strings */ = {
447 | isa = PBXVariantGroup;
448 | children = (
449 | 6003F597195388D20070C39A /* en */,
450 | );
451 | name = InfoPlist.strings;
452 | sourceTree = "";
453 | };
454 | 6003F5B8195388D20070C39A /* InfoPlist.strings */ = {
455 | isa = PBXVariantGroup;
456 | children = (
457 | 6003F5B9195388D20070C39A /* en */,
458 | );
459 | name = InfoPlist.strings;
460 | sourceTree = "";
461 | };
462 | /* End PBXVariantGroup section */
463 |
464 | /* Begin XCBuildConfiguration section */
465 | 6003F5BD195388D20070C39A /* Debug */ = {
466 | isa = XCBuildConfiguration;
467 | buildSettings = {
468 | ALWAYS_SEARCH_USER_PATHS = NO;
469 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
470 | CLANG_CXX_LIBRARY = "libc++";
471 | CLANG_ENABLE_MODULES = YES;
472 | CLANG_ENABLE_OBJC_ARC = YES;
473 | CLANG_WARN_BOOL_CONVERSION = YES;
474 | CLANG_WARN_CONSTANT_CONVERSION = YES;
475 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
476 | CLANG_WARN_EMPTY_BODY = YES;
477 | CLANG_WARN_ENUM_CONVERSION = YES;
478 | CLANG_WARN_INT_CONVERSION = YES;
479 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
480 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
481 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
482 | COPY_PHASE_STRIP = NO;
483 | GCC_C_LANGUAGE_STANDARD = gnu99;
484 | GCC_DYNAMIC_NO_PIC = NO;
485 | GCC_OPTIMIZATION_LEVEL = 0;
486 | GCC_PREPROCESSOR_DEFINITIONS = (
487 | "DEBUG=1",
488 | "$(inherited)",
489 | );
490 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
491 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
492 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
493 | GCC_WARN_UNDECLARED_SELECTOR = YES;
494 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
495 | GCC_WARN_UNUSED_FUNCTION = YES;
496 | GCC_WARN_UNUSED_VARIABLE = YES;
497 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
498 | ONLY_ACTIVE_ARCH = YES;
499 | SDKROOT = iphoneos;
500 | TARGETED_DEVICE_FAMILY = "1,2";
501 | };
502 | name = Debug;
503 | };
504 | 6003F5BE195388D20070C39A /* Release */ = {
505 | isa = XCBuildConfiguration;
506 | buildSettings = {
507 | ALWAYS_SEARCH_USER_PATHS = NO;
508 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
509 | CLANG_CXX_LIBRARY = "libc++";
510 | CLANG_ENABLE_MODULES = YES;
511 | CLANG_ENABLE_OBJC_ARC = YES;
512 | CLANG_WARN_BOOL_CONVERSION = YES;
513 | CLANG_WARN_CONSTANT_CONVERSION = YES;
514 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
515 | CLANG_WARN_EMPTY_BODY = YES;
516 | CLANG_WARN_ENUM_CONVERSION = YES;
517 | CLANG_WARN_INT_CONVERSION = YES;
518 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
519 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
520 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
521 | COPY_PHASE_STRIP = YES;
522 | ENABLE_NS_ASSERTIONS = NO;
523 | GCC_C_LANGUAGE_STANDARD = gnu99;
524 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
525 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
526 | GCC_WARN_UNDECLARED_SELECTOR = YES;
527 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
528 | GCC_WARN_UNUSED_FUNCTION = YES;
529 | GCC_WARN_UNUSED_VARIABLE = YES;
530 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
531 | SDKROOT = iphoneos;
532 | TARGETED_DEVICE_FAMILY = "1,2";
533 | VALIDATE_PRODUCT = YES;
534 | };
535 | name = Release;
536 | };
537 | 6003F5C0195388D20070C39A /* Debug */ = {
538 | isa = XCBuildConfiguration;
539 | baseConfigurationReference = 0E44244D22C6636AD5F992F4 /* Pods-VOXHistogramView_Example.debug.xcconfig */;
540 | buildSettings = {
541 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
542 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
543 | GCC_PREFIX_HEADER = "VOXHistogramView/VOXHistogramView-Prefix.pch";
544 | INFOPLIST_FILE = "VOXHistogramView/VOXHistogramView-Info.plist";
545 | MODULE_NAME = ExampleApp;
546 | PRODUCT_NAME = "$(TARGET_NAME)";
547 | WRAPPER_EXTENSION = app;
548 | };
549 | name = Debug;
550 | };
551 | 6003F5C1195388D20070C39A /* Release */ = {
552 | isa = XCBuildConfiguration;
553 | baseConfigurationReference = 102F05100418733F2372E3E8 /* Pods-VOXHistogramView_Example.release.xcconfig */;
554 | buildSettings = {
555 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
556 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
557 | GCC_PREFIX_HEADER = "VOXHistogramView/VOXHistogramView-Prefix.pch";
558 | INFOPLIST_FILE = "VOXHistogramView/VOXHistogramView-Info.plist";
559 | MODULE_NAME = ExampleApp;
560 | PRODUCT_NAME = "$(TARGET_NAME)";
561 | WRAPPER_EXTENSION = app;
562 | };
563 | name = Release;
564 | };
565 | 6003F5C3195388D20070C39A /* Debug */ = {
566 | isa = XCBuildConfiguration;
567 | baseConfigurationReference = 01213C494C6660BCE86E1EC1 /* Pods-VOXHistogramView_Tests.debug.xcconfig */;
568 | buildSettings = {
569 | BUNDLE_LOADER = "$(TEST_HOST)";
570 | FRAMEWORK_SEARCH_PATHS = (
571 | "$(SDKROOT)/Developer/Library/Frameworks",
572 | "$(inherited)",
573 | "$(DEVELOPER_FRAMEWORKS_DIR)",
574 | );
575 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
576 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
577 | GCC_PREPROCESSOR_DEFINITIONS = (
578 | "DEBUG=1",
579 | "$(inherited)",
580 | );
581 | INFOPLIST_FILE = "Tests/Tests-Info.plist";
582 | PRODUCT_NAME = "$(TARGET_NAME)";
583 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VOXHistogramView_Example.app/VOXHistogramView_Example";
584 | WRAPPER_EXTENSION = xctest;
585 | };
586 | name = Debug;
587 | };
588 | 6003F5C4195388D20070C39A /* Release */ = {
589 | isa = XCBuildConfiguration;
590 | baseConfigurationReference = 6004BC293FA95C142DA4FEB6 /* Pods-VOXHistogramView_Tests.release.xcconfig */;
591 | buildSettings = {
592 | BUNDLE_LOADER = "$(TEST_HOST)";
593 | FRAMEWORK_SEARCH_PATHS = (
594 | "$(SDKROOT)/Developer/Library/Frameworks",
595 | "$(inherited)",
596 | "$(DEVELOPER_FRAMEWORKS_DIR)",
597 | );
598 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
599 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
600 | INFOPLIST_FILE = "Tests/Tests-Info.plist";
601 | PRODUCT_NAME = "$(TARGET_NAME)";
602 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VOXHistogramView_Example.app/VOXHistogramView_Example";
603 | WRAPPER_EXTENSION = xctest;
604 | };
605 | name = Release;
606 | };
607 | /* End XCBuildConfiguration section */
608 |
609 | /* Begin XCConfigurationList section */
610 | 6003F585195388D10070C39A /* Build configuration list for PBXProject "VOXHistogramView" */ = {
611 | isa = XCConfigurationList;
612 | buildConfigurations = (
613 | 6003F5BD195388D20070C39A /* Debug */,
614 | 6003F5BE195388D20070C39A /* Release */,
615 | );
616 | defaultConfigurationIsVisible = 0;
617 | defaultConfigurationName = Release;
618 | };
619 | 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "VOXHistogramView_Example" */ = {
620 | isa = XCConfigurationList;
621 | buildConfigurations = (
622 | 6003F5C0195388D20070C39A /* Debug */,
623 | 6003F5C1195388D20070C39A /* Release */,
624 | );
625 | defaultConfigurationIsVisible = 0;
626 | defaultConfigurationName = Release;
627 | };
628 | 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "VOXHistogramView_Tests" */ = {
629 | isa = XCConfigurationList;
630 | buildConfigurations = (
631 | 6003F5C3195388D20070C39A /* Debug */,
632 | 6003F5C4195388D20070C39A /* Release */,
633 | );
634 | defaultConfigurationIsVisible = 0;
635 | defaultConfigurationName = Release;
636 | };
637 | /* End XCConfigurationList section */
638 | };
639 | rootObject = 6003F582195388D10070C39A /* Project object */;
640 | }
641 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView.xcodeproj/xcshareddata/xcschemes/VOXHistogramView-Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
14 |
20 |
21 |
22 |
28 |
34 |
35 |
36 |
37 |
38 |
43 |
44 |
46 |
52 |
53 |
54 |
55 |
56 |
62 |
63 |
64 |
65 |
74 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
94 |
100 |
101 |
102 |
103 |
105 |
106 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/Helpers/VOXJSONConverter.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 10/8/14.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 | @interface VOXJSONConverter : NSObject
30 |
31 | /**
32 | * Reads data from local file and returns NSDictionary or NSArray object
33 | *
34 | * @param fileName filename with extension
35 | *
36 | * @return NSArray or NSDictionary
37 | */
38 | + (id)jsonObjectWithFileName:(NSString *)fileName;
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/Helpers/VOXJSONConverter.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 10/8/14.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "VOXJSONConverter.h"
28 |
29 | @implementation VOXJSONConverter
30 |
31 | + (id)jsonObjectWithFileName:(NSString *)fileName
32 | {
33 | NSBundle *bundle = [NSBundle bundleForClass:self];
34 | NSString *path = [bundle pathForResource:fileName ofType:nil];
35 | NSData *jsonData = [NSData dataWithContentsOfFile:path];
36 | return [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:NULL];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/Helpers/VOXPlayerWrapper.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 26.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 | #import
29 |
30 | @class VOXPlayerWrapper;
31 |
32 |
33 |
34 | @protocol VOXPlayerWrapperDelegate
35 |
36 |
37 | @optional
38 | - (void)playerDidPause:(VOXPlayerWrapper *)playerWrapper;
39 | - (void)playerDidStartPlaying:(VOXPlayerWrapper *)playerWrapper;
40 | - (void)playerDidFinishCurrentTrack:(VOXPlayerWrapper *)playerWrapper;
41 | - (void) playerWrapper:(VOXPlayerWrapper *)playerWrapper
42 | downloadProgressChanged:(CGFloat)downloadProgress;
43 | - (void) playerWrapper:(VOXPlayerWrapper *)playerWrapper
44 | playbackProgressChanged:(CGFloat)playbackProgress;
45 |
46 |
47 | @end
48 |
49 |
50 |
51 | @interface VOXPlayerWrapper : NSObject
52 |
53 |
54 | #pragma mark - Init
55 | - (instancetype)initWithPlayer:(APAudioPlayer *)player NS_DESIGNATED_INITIALIZER;
56 | + (instancetype)wrapperWithPlayer:(APAudioPlayer *)player;
57 |
58 | #pragma mark - Delegate
59 | @property(nonatomic, weak) id delegate;
60 |
61 | #pragma mark - Player
62 | - (void)startPlayingTrackWithURL:(NSURL *)url;
63 | - (BOOL)isPlaying;
64 | - (void)play;
65 | - (void)pause;
66 | @property(nonatomic, assign) CGFloat position;
67 |
68 | /* Clean up timers to avoid retain cycle */
69 | - (void)cleanUp;
70 | @end
71 |
72 |
73 |
74 | @interface VOXPlayerWrapper (Unavailable)
75 |
76 |
77 | - (instancetype)init NS_UNAVAILABLE;
78 | + (instancetype)new NS_UNAVAILABLE;
79 |
80 | @end
--------------------------------------------------------------------------------
/Example/VOXHistogramView/Helpers/VOXPlayerWrapper.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 26.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 | #import "VOXPlayerWrapper.h"
29 |
30 |
31 | static NSUInteger const VOXDownloadTicksCount = 10;
32 |
33 |
34 |
35 | @interface VOXPlayerWrapper ()
36 |
37 |
38 | #pragma mark - Player
39 | @property(nonatomic, strong) APAudioPlayer *player;
40 |
41 | #pragma mark - Helpers
42 | @property(nonatomic, strong) NSTimer *progressTimer;
43 | @property(nonatomic, strong) NSTimer *downloadTimer;
44 | @property(nonatomic, assign) NSUInteger downloadTicksCount;
45 | @property(nonatomic, assign) CGFloat downloadProgress;
46 |
47 | @end
48 |
49 |
50 |
51 | @implementation VOXPlayerWrapper
52 |
53 |
54 | #pragma mark - Accessors
55 |
56 | - (CGFloat)position
57 | {
58 | return self.player.position;
59 | }
60 |
61 | - (void)setPosition:(CGFloat)position
62 | {
63 | [self.player setPosition:position];
64 | }
65 |
66 | #pragma mark - Init
67 |
68 | - (instancetype)initWithPlayer:(APAudioPlayer *)player
69 | {
70 | self = [super init];
71 | if (self) {
72 | self.player = player;
73 | self.player.delegate = self;
74 | }
75 | return self;
76 | }
77 |
78 | + (instancetype)wrapperWithPlayer:(APAudioPlayer *)player
79 | {
80 | return [[self alloc] initWithPlayer:player];
81 | }
82 |
83 | - (void)dealloc
84 | {
85 | [self _killDownloadTimer];
86 | [self _killTimer];
87 | }
88 |
89 | #pragma mark - Public
90 |
91 | - (void)startPlayingTrackWithURL:(NSURL *)url
92 | {
93 | [self.player loadItemWithURL:url autoPlay:NO];
94 | [self play];
95 | [self _startDownloadTimer];
96 | }
97 |
98 | - (BOOL)isPlaying
99 | {
100 | return self.player.isPlaying;
101 | }
102 |
103 | - (void)play
104 | {
105 | if (self.progressTimer) {
106 | [self _killTimer];
107 | }
108 |
109 | [self.player play];
110 | self.progressTimer = [NSTimer scheduledTimerWithTimeInterval:0.5f
111 | target:self
112 | selector:@selector(progressTimerFired:)
113 | userInfo:nil
114 | repeats:YES];
115 | }
116 |
117 | - (void)pause
118 | {
119 | [self.player pause];
120 | [self _killTimer];
121 | }
122 |
123 | - (void)cleanUp
124 | {
125 | [self _killDownloadTimer];
126 | [self _killTimer];
127 | }
128 |
129 | #pragma mark - APAudioPlayerDelegate
130 |
131 | - (void)playerDidChangePlayingStatus:(APAudioPlayer *)player
132 | {
133 | if ([player isPlaying]) {
134 | if ([self.delegate respondsToSelector:@selector(playerDidStartPlaying:)]) {
135 | [self.delegate playerDidStartPlaying:self];
136 | }
137 | }
138 | else if (player.position != 1.0f) {
139 | if ([self.delegate respondsToSelector:@selector(playerDidPause:)]) {
140 | [self.delegate playerDidPause:self];
141 | }
142 | }
143 | }
144 |
145 | - (void)playerDidFinishPlaying:(APAudioPlayer *)player
146 | {
147 | [self _startDownloadTimer];
148 | if ([self.delegate respondsToSelector:@selector(playerDidFinishCurrentTrack:)]) {
149 | [self.delegate playerDidFinishCurrentTrack:self];
150 | }
151 | [self play];
152 | }
153 |
154 | - (void)playerBeginInterruption:(APAudioPlayer *)player
155 | {
156 | [self pause];
157 | }
158 |
159 | - (void)playerEndInterruption:(APAudioPlayer *)player
160 | shouldResume:(BOOL)should
161 | {
162 | [self play];
163 | }
164 |
165 | #pragma mark - Timers
166 |
167 | - (void)progressTimerFired:(NSTimer *)sender
168 | {
169 | CGFloat playbackProgress = self.player.position;
170 | if ([self.delegate respondsToSelector:@selector(playerWrapper:playbackProgressChanged:)]) {
171 | [self.delegate playerWrapper:self playbackProgressChanged:playbackProgress];
172 | }
173 | }
174 |
175 | - (void)downloadTimerFired:(NSTimer *)sender
176 | {
177 | self.downloadTicksCount --;
178 | self.downloadProgress += 1.0f / VOXDownloadTicksCount;
179 | if ([self.delegate respondsToSelector:@selector(playerWrapper:downloadProgressChanged:)]) {
180 | [self.delegate playerWrapper:self downloadProgressChanged:self.downloadProgress];
181 | }
182 | if (self.downloadTicksCount == 0) {
183 | [self _killDownloadTimer];
184 | }
185 | }
186 |
187 | #pragma mark - Helpers
188 |
189 | - (void)_killTimer
190 | {
191 | [self.progressTimer invalidate];
192 | self.progressTimer = nil;
193 | }
194 |
195 | - (void)_startDownloadTimer
196 | {
197 | self.downloadTicksCount = VOXDownloadTicksCount;
198 | self.downloadProgress = 0.0f;
199 | self.downloadTimer = [NSTimer scheduledTimerWithTimeInterval:0.3f
200 | target:self
201 | selector:@selector(downloadTimerFired:)
202 | userInfo:nil
203 | repeats:YES];
204 | }
205 |
206 | - (void)_killDownloadTimer
207 | {
208 | [self.downloadTimer invalidate];
209 | self.downloadTimer = nil;
210 | }
211 |
212 |
213 | @end
--------------------------------------------------------------------------------
/Example/VOXHistogramView/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/Resources/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/Example/VOXHistogramView/Resources/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "ipad",
6 | "minimum-system-version" : "7.0",
7 | "extent" : "full-screen",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "landscape",
12 | "idiom" : "ipad",
13 | "minimum-system-version" : "7.0",
14 | "extent" : "full-screen",
15 | "scale" : "1x"
16 | },
17 | {
18 | "orientation" : "landscape",
19 | "idiom" : "ipad",
20 | "minimum-system-version" : "7.0",
21 | "extent" : "full-screen",
22 | "scale" : "2x"
23 | },
24 | {
25 | "orientation" : "portrait",
26 | "idiom" : "iphone",
27 | "minimum-system-version" : "7.0",
28 | "scale" : "2x"
29 | },
30 | {
31 | "orientation" : "portrait",
32 | "idiom" : "iphone",
33 | "minimum-system-version" : "7.0",
34 | "subtype" : "retina4",
35 | "scale" : "2x"
36 | },
37 | {
38 | "orientation" : "portrait",
39 | "idiom" : "ipad",
40 | "minimum-system-version" : "7.0",
41 | "extent" : "full-screen",
42 | "scale" : "1x"
43 | }
44 | ],
45 | "info" : {
46 | "version" : 1,
47 | "author" : "xcode"
48 | }
49 | }
--------------------------------------------------------------------------------
/Example/VOXHistogramView/Resources/levels.json:
--------------------------------------------------------------------------------
1 | [
2 | 0.6595238095238095,
3 | 0.8738095238095238,
4 | 0.87142857142857143333333333333333333333,
5 | 0.85952380952380953333333333333333333333,
6 | 0.84047619047619046666666666666666666666,
7 | 0.85476190476190476666666666666666666666,
8 | 0.8785714285714286,
9 | 0.9,
10 | 0.86190476190476193333333333333333333333,
11 | 0.85952380952380953333333333333333333333,
12 | 0.8880952380952381,
13 | 0.90238095238095236666666666666666666666,
14 | 0.94523809523809523333333333333333333333,
15 | 0.8761904761904762,
16 | 0.87857142857142856666666666666666666666,
17 | 0.8857142857142857,
18 | 0.87857142857142856666666666666666666666,
19 | 0.88095238095238093333333333333333333333,
20 | 0.84523809523809526666666666666666666666,
21 | 0.88095238095238093333333333333333333333,
22 | 0.9023809523809524,
23 | 0.84285714285714283333333333333333333333,
24 | 0.9023809523809524,
25 | 0.85,
26 | 0.8738095238095238,
27 | 0.89761904761904763333333333333333333333,
28 | 0.87142857142857143333333333333333333333,
29 | 0.86666666666666666666666666666666666666,
30 | 0.87857142857142856666666666666666666666,
31 | 0.90714285714285716666666666666666666666,
32 | 0.88571428571428573333333333333333333333,
33 | 0.85714285714285716666666666666666666666,
34 | 0.90476190476190476666666666666666666666,
35 | 0.89285714285714283333333333333333333333,
36 | 0.86904761904761906666666666666666666666,
37 | 0.8738095238095238,
38 | 0.89047619047619046666666666666666666666,
39 | 0.90714285714285713333333333333333333333,
40 | 0.87857142857142856666666666666666666666,
41 | 0.85952380952380953333333333333333333333,
42 | 0.8785714285714286,
43 | 0.9166666666666667,
44 | 0.9119047619047619,
45 | 0.87380952380952383333333333333333333333,
46 | 0.8833333333333333,
47 | 0.89047619047619046666666666666666666666,
48 | 0.8619047619047619,
49 | 0.88333333333333333333333333333333333333,
50 | 0.89285714285714283333333333333333333333,
51 | 0.8880952380952381,
52 | 0.9023809523809524,
53 | 0.89523809523809523333333333333333333333,
54 | 0.8880952380952381,
55 | 0.85,
56 | 0.8523809523809524,
57 | 0.90714285714285713333333333333333333333,
58 | 0.8761904761904762,
59 | 0.84523809523809526666666666666666666666,
60 | 0.8738095238095238,
61 | 0.8619047619047619,
62 | 0.8738095238095238,
63 | 0.90714285714285713333333333333333333333,
64 | 0.85714285714285716666666666666666666666,
65 | 0.8880952380952381,
66 | 0.86428571428571426666666666666666666666,
67 | 0.9095238095238095,
68 | 0.8761904761904762,
69 | 0.85952380952380953333333333333333333333,
70 | 0.90714285714285716666666666666666666666,
71 | 0.8761904761904762,
72 | 0.8880952380952381,
73 | 0.90714285714285716666666666666666666666,
74 | 0.84523809523809523333333333333333333333,
75 | 0.9,
76 | 0.88571428571428573333333333333333333333,
77 | 0.89523809523809523333333333333333333333,
78 | 0.89761904761904763333333333333333333333,
79 | 0.90476190476190476666666666666666666666,
80 | 0.89761904761904763333333333333333333333,
81 | 0.8857142857142857,
82 | 0.8761904761904762,
83 | 0.87142857142857143333333333333333333333,
84 | 0.89047619047619046666666666666666666666,
85 | 0.8666666666666667,
86 | 0.85476190476190476666666666666666666666,
87 | 0.8880952380952381,
88 | 0.87380952380952383333333333333333333333,
89 | 0.86904761904761903333333333333333333333,
90 | 0.92619047619047616666666666666666666666,
91 | 0.88333333333333333333333333333333333333,
92 | 0.85,
93 | 0.85952380952380953333333333333333333333,
94 | 0.8619047619047619,
95 | 0.8738095238095238,
96 | 0.86666666666666666666666666666666666666,
97 | 0.8880952380952381,
98 | 0.86904761904761906666666666666666666666,
99 | 0.8880952380952381,
100 | 0.90952380952380953333333333333333333333,
101 | 0.8738095238095238,
102 | 0.8642857142857143,
103 | 0.8880952380952381,
104 | 0.88095238095238096666666666666666666666,
105 | 0.87619047619047616666666666666666666666,
106 | 0.8642857142857143,
107 | 0.8976190476190476,
108 | 0.86428571428571426666666666666666666666,
109 | 0.9095238095238095,
110 | 0.94047619047619046666666666666666666666,
111 | 0.8857142857142857,
112 | 0.90476190476190473333333333333333333333,
113 | 0.88333333333333333333333333333333333333,
114 | 0.90238095238095236666666666666666666666,
115 | 0.88809523809523806666666666666666666666,
116 | 0.8714285714285714,
117 | 0.87142857142857143333333333333333333333,
118 | 0.8619047619047619,
119 | 0.85,
120 | 0.88333333333333333333333333333333333333,
121 | 0.87380952380952383333333333333333333333,
122 | 0.84999999999999996666666666666666666666,
123 | 0.9261904761904762,
124 | 0.9142857142857143,
125 | 0.88333333333333333333333333333333333333,
126 | 0.8595238095238095,
127 | 0.70952380952380953333333333333333333333,
128 | 0.09047619047619048,
129 | 0.09047619047619048,
130 | 0.09047619047619048,
131 | 0.09523809523809524,
132 | 0.09523809523809524,
133 | 0.09523809523809524,
134 | 0.09523809523809524,
135 | 0.09761904761904762,
136 | 0.09523809523809524,
137 | 0.09285714285714286,
138 | 0.1,
139 | 0.09285714285714286,
140 | 0.102380952380952366666666666666666666666,
141 | 0.09761904761904762,
142 | 0.1,
143 | 0.09761904761904762,
144 | 0.102380952380952366666666666666666666666,
145 | 0.1,
146 | 0.09761904761904762,
147 | 0.1,
148 | 0.09761904761904762,
149 | 0.1,
150 | 0.09523809523809524,
151 | 0.102380952380952366666666666666666666666,
152 | 0.09761904761904762,
153 | 0.1,
154 | 0.09761904761904762,
155 | 0.09523809523809524,
156 | 0.102380952380952366666666666666666666666,
157 | 0.1,
158 | 0.1,
159 | 0.1,
160 | 0.09761904761904762,
161 | 0.1,
162 | 0.1,
163 | 0.1,
164 | 0.1,
165 | 0.1,
166 | 0.09761904761904762,
167 | 0.1,
168 | 0.1,
169 | 0.09761904761904762,
170 | 0.1,
171 | 0.1,
172 | 0.1,
173 | 0.09523809523809524,
174 | 0.1,
175 | 0.1,
176 | 0.1,
177 | 0.102380952380952366666666666666666666666,
178 | 0.1,
179 | 0.09761904761904762,
180 | 0.099999999999999986666666666666666666666,
181 | 0.09523809523809524,
182 | 0.09761904761904762,
183 | 0.1,
184 | 0.1,
185 | 0.1,
186 | 0.1,
187 | 0.1,
188 | 0.102380952380952366666666666666666666666,
189 | 0.09761904761904762,
190 | 0.1,
191 | 0.1,
192 | 0.09761904761904762,
193 | 0.09523809523809524,
194 | 0.099999999999999986666666666666666666666,
195 | 0.09761904761904762,
196 | 0.1,
197 | 0.09761904761904762,
198 | 0.09761904761904762,
199 | 0.1,
200 | 0.1,
201 | 0.09761904761904762,
202 | 0.1,
203 | 0.09761904761904762,
204 | 0.1,
205 | 0.1,
206 | 0.09761904761904762,
207 | 0.099999999999999986666666666666666666666,
208 | 0.1,
209 | 0.09761904761904762,
210 | 0.09761904761904762,
211 | 0.1,
212 | 0.09761904761904762,
213 | 0.09761904761904762,
214 | 0.09761904761904762,
215 | 0.09761904761904762,
216 | 0.1,
217 | 0.1,
218 | 0.09761904761904762,
219 | 0.1,
220 | 0.09285714285714286,
221 | 0.1,
222 | 0.09761904761904762,
223 | 0.1,
224 | 0.099999999999999986666666666666666666666,
225 | 0.1,
226 | 0.099999999999999986666666666666666666666,
227 | 0.1,
228 | 0.1,
229 | 0.099999999999999986666666666666666666666,
230 | 0.1,
231 | 0.1,
232 | 0.1,
233 | 0.09761904761904762,
234 | 0.1,
235 | 0.09523809523809524,
236 | 0.09761904761904762,
237 | 0.09761904761904762,
238 | 0.1,
239 | 0.09761904761904762,
240 | 0.1,
241 | 0.1,
242 | 0.1,
243 | 0.1,
244 | 0.1,
245 | 0.09761904761904762,
246 | 0.09761904761904762,
247 | 0.09761904761904762,
248 | 0.1,
249 | 0.1,
250 | 0.09761904761904762,
251 | 0.1
252 | ]
--------------------------------------------------------------------------------
/Example/VOXHistogramView/Resources/pink20silence20.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Coppertino/VOXHistogramView/aae79f0089eb3d724c3ecb689c061fd0d731fe9f/Example/VOXHistogramView/Resources/pink20silence20.mp3
--------------------------------------------------------------------------------
/Example/VOXHistogramView/VOXAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 02.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 |
30 |
31 | @interface VOXAppDelegate : UIResponder
32 |
33 |
34 | @property(strong, nonatomic) UIWindow *window;
35 |
36 |
37 | @end
38 |
39 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/VOXAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 02.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "VOXAppDelegate.h"
28 |
29 |
30 |
31 | @interface VOXAppDelegate ()
32 |
33 | @end
34 |
35 |
36 |
37 | @implementation VOXAppDelegate
38 |
39 |
40 | - (BOOL) application:(UIApplication *)application
41 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
42 | {
43 | // Override point for customization after application launch.
44 | return YES;
45 | }
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/VOXHistogramView-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UIRequiredDeviceCapabilities
32 |
33 | armv7
34 |
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationLandscapeLeft
39 | UIInterfaceOrientationLandscapeRight
40 |
41 | UISupportedInterfaceOrientations~ipad
42 |
43 | UIInterfaceOrientationPortrait
44 | UIInterfaceOrientationPortraitUpsideDown
45 | UIInterfaceOrientationLandscapeLeft
46 | UIInterfaceOrientationLandscapeRight
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/VOXHistogramView-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #import
8 |
9 | #ifndef __IPHONE_5_0
10 | #warning "This project uses features only available in iOS SDK 5.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | @import UIKit;
15 | @import Foundation;
16 | #endif
17 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/ViewControllers/VOXControlHistogramViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 24.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 |
30 |
31 | @interface VOXControlHistogramViewController : UIViewController
32 | @end
--------------------------------------------------------------------------------
/Example/VOXHistogramView/ViewControllers/VOXControlHistogramViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 24.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "VOXControlHistogramViewController.h"
28 | #import "VOXJSONConverter.h"
29 | #import "VOXPlayerWrapper.h"
30 | #import
31 |
32 |
33 |
34 | @interface VOXControlHistogramViewController ()
35 |
36 |
37 | #pragma mark - Outlets
38 | @property(weak, nonatomic) IBOutlet UIButton *playButton;
39 | @property(weak, nonatomic) IBOutlet VOXHistogramControlView *histogramControlView;
40 | @property(weak, nonatomic) IBOutlet UILabel *scrubbingSpeedLabel;
41 |
42 | #pragma mark - Player Wrapper
43 | @property(nonatomic, strong) VOXPlayerWrapper *playerWrapper;
44 | @end
45 |
46 |
47 |
48 | @implementation VOXControlHistogramViewController
49 |
50 |
51 | #pragma mark - Lifecycle
52 |
53 | - (void)viewDidLoad
54 | {
55 | [super viewDidLoad];
56 |
57 | self.histogramControlView.delegate = self;
58 |
59 | self.playerWrapper = [[VOXPlayerWrapper alloc] initWithPlayer:[APAudioPlayer new]];
60 | self.playerWrapper.delegate = self;
61 |
62 | self.scrubbingSpeedLabel.alpha = 0.0f;
63 | }
64 |
65 | - (void)viewDidAppear:(BOOL)animated
66 | {
67 | [super viewDidAppear:animated];
68 |
69 | /* Load levels JSON */
70 | NSArray *levels = [VOXJSONConverter jsonObjectWithFileName:@"levels.json"];
71 | self.histogramControlView.levels = levels;
72 |
73 | NSString *path = [[NSBundle mainBundle] pathForResource:@"pink20silence20" ofType:@"mp3"];
74 | [self.playerWrapper startPlayingTrackWithURL:[NSURL URLWithString:path]];
75 | }
76 |
77 | - (void)dealloc
78 | {
79 | [self.playerWrapper cleanUp];
80 | }
81 |
82 |
83 | #pragma mark - Actions
84 |
85 | - (IBAction)playButtonTap:(id)sender
86 | {
87 | if ([self.playerWrapper isPlaying]) {
88 | [self.playerWrapper pause];
89 | }
90 | else {
91 | [self.playerWrapper play];
92 | }
93 | }
94 |
95 | #pragma mark - VOXPlayerWrapperDelegate
96 |
97 | - (void)playerDidPause:(VOXPlayerWrapper *)playerWrapper
98 | {
99 | [self.playButton setTitle:@"Play" forState:UIControlStateNormal];
100 | [self.histogramControlView hideHistogramViewAnimated:YES];
101 | }
102 |
103 | - (void)playerDidStartPlaying:(VOXPlayerWrapper *)playerWrapper
104 | {
105 | [self.playButton setTitle:@"Pause" forState:UIControlStateNormal];
106 | [self.histogramControlView showHistogramViewAnimated:YES];
107 | }
108 |
109 | - (void)playerDidFinishCurrentTrack:(VOXPlayerWrapper *)playerWrapper
110 | {
111 | self.histogramControlView.playbackProgress = 0.0f;
112 | }
113 |
114 | - (void) playerWrapper:(VOXPlayerWrapper *)playerWrapper
115 | downloadProgressChanged:(CGFloat)downloadProgress
116 | {
117 | self.histogramControlView.downloadProgress = downloadProgress;
118 | }
119 |
120 | - (void) playerWrapper:(VOXPlayerWrapper *)playerWrapper
121 | playbackProgressChanged:(CGFloat)playbackProgress
122 | {
123 | self.histogramControlView.playbackProgress = playbackProgress;
124 | }
125 |
126 | #pragma mark - VOXHistogramControlViewDelegate
127 |
128 | - (void)histogramControlViewDidFinishRendering:(VOXHistogramControlView *)controlView
129 | {
130 | [self.histogramControlView showHistogramViewAnimated:YES];
131 | }
132 |
133 | - (void)histogramControlView:(VOXHistogramControlView *)controlView
134 | didChangeScrubbingSpeed:(CGFloat)scrubbingSpeed
135 | {
136 | [self _updateScrubbingSpeedLabel:scrubbingSpeed];
137 | }
138 |
139 | - (void)histogramControlViewDidStartTracking:(VOXHistogramControlView *)controlView
140 | {
141 | [self.histogramControlView showHistogramViewAnimated:YES];
142 | [self _animateScrubbingSpeedLabel:YES];
143 | [self _updateScrubbingSpeedLabel:controlView.scrubbingSpeed];
144 | }
145 |
146 | - (void) histogramControlView:(VOXHistogramControlView *)controlView
147 | didFinishTrackingWithProgress:(CGFloat)value
148 | {
149 | if (! [self.playerWrapper isPlaying]) {
150 | [self.histogramControlView hideHistogramViewAnimated:YES];
151 | }
152 | [self _animateScrubbingSpeedLabel:NO];
153 | self.playerWrapper.position = value;
154 | }
155 |
156 | #pragma mark - Private
157 |
158 | - (void)_updateScrubbingSpeedLabel:(CGFloat)scrubbingSpeed
159 | {
160 | self.scrubbingSpeedLabel.text = [NSString stringWithFormat:@"%@: %.0f%%", NSLocalizedString(@"Scrubbing speed", nil),
161 | scrubbingSpeed * 100];
162 | }
163 |
164 | - (void)_animateScrubbingSpeedLabel:(BOOL)show
165 | {
166 | [UIView animateWithDuration:0.25f animations:^{
167 | self.scrubbingSpeedLabel.alpha = show ? 1.0f : 0.0f;
168 | }];
169 | }
170 |
171 | @end
--------------------------------------------------------------------------------
/Example/VOXHistogramView/ViewControllers/VOXSimpleHistogramViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 02.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 |
30 |
31 | @interface VOXSimpleHistogramViewController : UIViewController
32 |
33 |
34 | @end
35 |
36 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/ViewControllers/VOXSimpleHistogramViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 02.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 | #import
29 | #import
30 | #import
31 | #import "VOXSimpleHistogramViewController.h"
32 | #import "VOXJSONConverter.h"
33 | #import "VOXPlayerWrapper.h"
34 |
35 |
36 |
37 | @interface VOXSimpleHistogramViewController ()
38 |
39 |
40 | #pragma mark - Outlets
41 | @property(weak, nonatomic) IBOutlet UIButton *playButton;
42 | @property(weak, nonatomic) IBOutlet VOXHistogramView *histogramView;
43 |
44 | #pragma mark - Player
45 | @property(nonatomic, strong) VOXPlayerWrapper *playerWrapper;
46 |
47 | @end
48 |
49 |
50 |
51 | @implementation VOXSimpleHistogramViewController
52 |
53 |
54 | #pragma mark - Lifecycle
55 |
56 | - (void)viewDidLoad
57 | {
58 | [super viewDidLoad];
59 |
60 | self.playerWrapper = [[VOXPlayerWrapper alloc] initWithPlayer:[APAudioPlayer new]];
61 | self.playerWrapper.delegate = self;
62 | }
63 |
64 | - (void)viewDidAppear:(BOOL)animated
65 | {
66 | [super viewDidAppear:animated];
67 |
68 | /* Histogram params */
69 | NSUInteger peakWidth = 4;
70 | NSUInteger marginWidth = 2;
71 |
72 | /* Setup rendering configuration */
73 | VOXHistogramRenderingConfiguration *renderingConfiguration = [VOXHistogramRenderingConfiguration new];
74 | renderingConfiguration.outputImageSize = self.histogramView.bounds.size;
75 | renderingConfiguration.renderingMode = UIImageRenderingModeAlwaysTemplate;
76 | renderingConfiguration.peaksColor = [UIColor whiteColor];
77 | renderingConfiguration.peakWidth = peakWidth;
78 | renderingConfiguration.marginWidth = marginWidth;
79 |
80 | /* Create renderer for histogram image */
81 | VOXHistogramRenderer *renderer = [VOXHistogramRenderer rendererWithRenderingConfiguration:renderingConfiguration];
82 |
83 | /* Load levels JSON */
84 | NSArray *levels = [VOXJSONConverter jsonObjectWithFileName:@"levels.json"];
85 |
86 | /* Setup levels converter */
87 | VOXHistogramLevelsConverter *converter = [VOXHistogramLevelsConverter new];
88 | [converter updateLevels:levels];
89 |
90 | /* Calculate number of levels that histogram can display in current bounds */
91 | NSUInteger samplingRate = [self _samplingRateForHistogramWidth:CGRectGetWidth(self.histogramView.bounds)
92 | peakWidth:peakWidth
93 | marginWidth:marginWidth];
94 |
95 | /* Convert levels array to sampling rate and render histogram image */
96 | [converter calculateLevelsForSamplingRate:samplingRate completion:^(NSArray *levelsResampled) {
97 | [renderer renderHistogramWithLevels:levelsResampled completion:^(UIImage *image) {\
98 | self.histogramView.image = image;
99 | }];
100 | }];
101 |
102 | NSString *path = [[NSBundle mainBundle] pathForResource:@"pink20silence20" ofType:@"mp3"];
103 | [self.playerWrapper startPlayingTrackWithURL:[NSURL URLWithString:path]];
104 | }
105 |
106 | - (void)dealloc
107 | {
108 | [self.playerWrapper cleanUp];
109 | }
110 |
111 |
112 | #pragma mark - Actions
113 |
114 | - (IBAction)playButtonTap:(id)sender
115 | {
116 | if ([self.playerWrapper isPlaying]) {
117 | [self.playerWrapper pause];
118 | }
119 | else {
120 | [self.playerWrapper play];
121 | }
122 | }
123 |
124 | #pragma mark - VOXPlayerWrapperDelegate
125 |
126 | - (void)playerDidPause:(VOXPlayerWrapper *)playerWrapper
127 | {
128 | [self.playButton setTitle:@"Play" forState:UIControlStateNormal];
129 | }
130 |
131 | - (void)playerDidStartPlaying:(VOXPlayerWrapper *)playerWrapper
132 | {
133 | [self.playButton setTitle:@"Pause" forState:UIControlStateNormal];
134 | }
135 |
136 | - (void)playerDidFinishCurrentTrack:(VOXPlayerWrapper *)playerWrapper
137 | {
138 | [self.histogramView updatePlaybackProgress:0.0f];
139 | }
140 |
141 | - (void) playerWrapper:(VOXPlayerWrapper *)playerWrapper
142 | playbackProgressChanged:(CGFloat)playbackProgress
143 | {
144 | [self.histogramView updatePlaybackProgress:playbackProgress];
145 | }
146 |
147 | - (void) playerWrapper:(VOXPlayerWrapper *)playerWrapper
148 | downloadProgressChanged:(CGFloat)downloadProgress
149 | {
150 | [self.histogramView updateDownloadProgress:downloadProgress];
151 | }
152 |
153 | #pragma mark - Private
154 |
155 | - (NSUInteger)_samplingRateForHistogramWidth:(CGFloat)histogramWidth
156 | peakWidth:(CGFloat)peakWidth
157 | marginWidth:(CGFloat)marginWidth
158 | {
159 | CGFloat scale = [UIScreen mainScreen].scale;
160 | return (NSUInteger) ceilf((histogramWidth / (peakWidth + marginWidth)) * scale);
161 | }
162 |
163 | @end
164 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/ViewControllers/VOXTableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 17.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 |
30 |
31 | @interface VOXTableViewController : UITableViewController
32 | @end
--------------------------------------------------------------------------------
/Example/VOXHistogramView/ViewControllers/VOXTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 17.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "VOXTableViewController.h"
28 |
29 |
30 |
31 | @implementation VOXTableViewController
32 |
33 |
34 | @end
--------------------------------------------------------------------------------
/Example/VOXHistogramView/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/VOXHistogramView/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // VOXHistogramView
4 | //
5 | // Created by Nickolay Sheika on 06/27/2015.
6 | // Copyright (c) 2014 Nickolay Sheika. All rights reserved.
7 | //
8 |
9 | @import UIKit;
10 | #import "VOXAppDelegate.h"
11 |
12 | int main(int argc, char * argv[])
13 | {
14 | @autoreleasepool {
15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([VOXAppDelegate class]));
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Gif/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Coppertino/VOXHistogramView/aae79f0089eb3d724c3ecb689c061fd0d731fe9f/Gif/demo.gif
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 Coppertino Inc. (http://coppertino.com/)
2 |
3 | VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
4 | Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
5 | Contact phone: +1 (888) 765-7069
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
--------------------------------------------------------------------------------
/Pod/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Coppertino/VOXHistogramView/aae79f0089eb3d724c3ecb689c061fd0d731fe9f/Pod/Assets/.gitkeep
--------------------------------------------------------------------------------
/Pod/Classes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Coppertino/VOXHistogramView/aae79f0089eb3d724c3ecb689c061fd0d731fe9f/Pod/Classes/.gitkeep
--------------------------------------------------------------------------------
/Pod/Classes/Animator/VOXHistogramAnimator.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 23.01.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 | @class VOXHistogramAnimator;
30 |
31 |
32 |
33 | @protocol VOXHistogramAnimatorDelegate
34 |
35 |
36 | - (void)histogramAnimatorWillShowHistogram:(VOXHistogramAnimator *)controlView;
37 | - (void)histogramAnimatorDidShowHistogram:(VOXHistogramAnimator *)controlView;
38 | - (void)histogramAnimatorWillHideHistogram:(VOXHistogramAnimator *)controlView;
39 | - (void)histogramAnimatorDidHideHistogram:(VOXHistogramAnimator *)controlView;
40 |
41 | @end
42 |
43 |
44 |
45 | @interface VOXHistogramAnimator : NSObject
46 |
47 |
48 | #pragma mark - Delegate
49 | @property(nonatomic, weak) id delegate;
50 |
51 | #pragma mark - State
52 | @property(nonatomic, assign, readonly) BOOL histogramPresented;
53 | @property(nonatomic, assign, readonly) BOOL animating;
54 |
55 | #pragma mark - Managed Views
56 | @property(nonatomic, weak, readonly) UIView *histogramView;
57 |
58 | #pragma mark - Show / Hide Histogram
59 | - (void)showHistogramViewAnimated:(BOOL)animated;
60 | - (void)hideHistogramViewAnimated:(BOOL)animated;
61 |
62 | #pragma mark - Designated Initializer
63 | - (instancetype)initWithHistogramView:(UIView *)histogramView;
64 | + (instancetype)animatorWithHistogramView:(UIView *)histogramView;
65 |
66 |
67 | @end
--------------------------------------------------------------------------------
/Pod/Classes/Animator/VOXHistogramAnimator.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 23.01.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "VOXHistogramAnimator.h"
28 |
29 | static CGFloat const VOXHistogramAnimatorAnimationDuration = 0.25f;
30 |
31 |
32 |
33 | @interface VOXHistogramAnimator ()
34 |
35 |
36 | #pragma mark - Public
37 | @property(nonatomic, weak, readwrite) UIView *histogramView;
38 | @property(nonatomic, assign, readwrite, getter=didHistogramShowed) BOOL histogramPresented;
39 |
40 | #pragma mark - Helpers
41 | @property(nonatomic, assign) BOOL animatingShowHistogram;
42 | @property(nonatomic, assign) BOOL animatingHideHistogram;
43 |
44 | @end
45 |
46 |
47 |
48 | @implementation VOXHistogramAnimator
49 |
50 |
51 | #pragma mark - Accessors
52 |
53 | - (BOOL)animating
54 | {
55 | return self.animatingHideHistogram || self.animatingShowHistogram;
56 | }
57 |
58 | #pragma mark - Init
59 |
60 | - (instancetype)initWithHistogramView:(UIView *)histogramView
61 | {
62 | self = [super init];
63 | if (self) {
64 | self.histogramView = histogramView;
65 | self.histogramPresented = YES;
66 | }
67 | return self;
68 | }
69 |
70 | + (instancetype)animatorWithHistogramView:(UIView *)histogramView
71 | {
72 | return [[self alloc] initWithHistogramView:histogramView];
73 | }
74 |
75 | #pragma mark - Public
76 |
77 | - (void)showHistogramViewAnimated:(BOOL)animated
78 | {
79 | if ((self.histogramPresented && ! self.animatingHideHistogram) || self.animatingShowHistogram)
80 | return;
81 |
82 | if ([self.delegate respondsToSelector:@selector(histogramAnimatorWillShowHistogram:)]) {
83 | [self.delegate histogramAnimatorWillShowHistogram:self];
84 | }
85 |
86 | void (^animations)() = ^{
87 | [self transformToShowedState];
88 | };
89 | void (^completion)(BOOL) = ^(BOOL finished) {
90 | self.animatingShowHistogram = NO;
91 | if (finished) {
92 | self.histogramPresented = YES;
93 | if ([self.delegate respondsToSelector:@selector(histogramAnimatorDidShowHistogram:)]) {
94 | [self.delegate histogramAnimatorDidShowHistogram:self];
95 | }
96 | }
97 | };
98 |
99 | if (animated) {
100 | self.animatingShowHistogram = YES;
101 | [self makeTransitionAnimationWithAnimations:animations
102 | andCompletion:completion];
103 | }
104 | else {
105 | animations();
106 | completion(YES);
107 | }
108 | }
109 |
110 | - (void)hideHistogramViewAnimated:(BOOL)animated
111 | {
112 | if ((! self.histogramPresented && ! self.animatingShowHistogram) || self.animatingHideHistogram)
113 | return;
114 |
115 | if ([self.delegate respondsToSelector:@selector(histogramAnimatorWillHideHistogram:)]) {
116 | [self.delegate histogramAnimatorWillHideHistogram:self];
117 | }
118 |
119 | void (^animations)() = ^{
120 | [self transformToHiddenState];
121 | };
122 | void (^completion)(BOOL) = ^(BOOL finished) {
123 | self.animatingHideHistogram = NO;
124 | if (finished) {
125 | self.histogramPresented = NO;
126 | if ([self.delegate respondsToSelector:@selector(histogramAnimatorDidHideHistogram:)]) {
127 | [self.delegate histogramAnimatorDidHideHistogram:self];
128 | }
129 | }
130 | };
131 |
132 | if (animated) {
133 | self.animatingHideHistogram = YES;
134 | [self makeTransitionAnimationWithAnimations:animations
135 | andCompletion:completion];
136 | }
137 | else {
138 | animations();
139 | completion(YES);
140 | }
141 | }
142 |
143 | #pragma mark - Animations
144 |
145 | - (void)makeTransitionAnimationWithAnimations:(void (^)(void))animations
146 | andCompletion:(void (^)(BOOL finished))completion
147 | {
148 | [UIView animateWithDuration:VOXHistogramAnimatorAnimationDuration
149 | delay:0.0f
150 | usingSpringWithDamping:0.9f
151 | initialSpringVelocity:0.8f
152 | options:UIViewAnimationOptionBeginFromCurrentState
153 | animations:animations
154 | completion:completion];
155 | }
156 |
157 | #pragma mark - Frames Setup
158 |
159 | - (void)transformToHiddenState
160 | {
161 | CGFloat histogramHeight = CGRectGetHeight(self.histogramView.frame);
162 | CGAffineTransform translation = CGAffineTransformMakeTranslation(0.0f, histogramHeight / 2);
163 | CGAffineTransform scale = CGAffineTransformMakeScale(1.0f, 0.00001f);
164 | CGAffineTransform transform = CGAffineTransformConcat(scale, translation);
165 | self.histogramView.transform = transform;
166 | }
167 |
168 | - (void)transformToShowedState
169 | {
170 | self.histogramView.transform = CGAffineTransformIdentity;
171 | }
172 |
173 | @end
--------------------------------------------------------------------------------
/Pod/Classes/Categories/UIView+Autolayout.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 25.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 |
30 |
31 | @interface UIView (Autolayout)
32 |
33 | + (instancetype)autolayoutView;
34 |
35 | @end
--------------------------------------------------------------------------------
/Pod/Classes/Categories/UIView+Autolayout.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 25.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "UIView+Autolayout.h"
28 |
29 |
30 |
31 | @implementation UIView (Autolayout)
32 |
33 |
34 | + (instancetype)autolayoutView
35 | {
36 | UIView *view = [[self alloc] initWithFrame:CGRectZero];
37 | view.translatesAutoresizingMaskIntoConstraints = NO;
38 | return view;
39 | }
40 |
41 |
42 | @end
--------------------------------------------------------------------------------
/Pod/Classes/Configurations/VOXHistogramRenderingConfiguration.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 14.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 |
30 |
31 | @interface VOXHistogramRenderingConfiguration : NSObject
32 |
33 | /**
34 | * Size of resulting image
35 | */
36 | @property(nonatomic, assign) CGSize outputImageSize;
37 |
38 | /**
39 | * Image rendering mode
40 | */
41 | @property(nonatomic, assign) UIImageRenderingMode renderingMode;
42 |
43 | /**
44 | * Width if one peak in pixels (not points!)
45 | */
46 | @property(nonatomic, assign) NSUInteger peakWidth;
47 |
48 | /**
49 | * Margin between two peaks in pixels (not points!)
50 | */
51 | @property(nonatomic, assign) NSUInteger marginWidth;
52 |
53 | /**
54 | * Color of peaks
55 | */
56 | @property(nonatomic, strong) UIColor *peaksColor;
57 |
58 | @end
--------------------------------------------------------------------------------
/Pod/Classes/Configurations/VOXHistogramRenderingConfiguration.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 14.06.15.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "VOXHistogramRenderingConfiguration.h"
28 |
29 |
30 |
31 | @implementation VOXHistogramRenderingConfiguration
32 |
33 |
34 | @end
--------------------------------------------------------------------------------
/Pod/Classes/LevelsConverter/VOXHistogramLevelsConverter.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 10/9/14.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 |
30 |
31 | @interface VOXHistogramLevelsConverter : NSObject
32 |
33 |
34 | /*
35 | @value full levels array
36 | */
37 | @property(nonatomic, strong, readonly) NSArray *levels;
38 |
39 | #pragma mark - Data Updating
40 | - (void)updateLevels:(NSArray *)levels;
41 |
42 | #pragma mark - Get histogram data
43 | - (void)calculateLevelsForSamplingRate:(NSUInteger)samplingRate
44 | completion:(void (^)(NSArray *levels))completion;
45 |
46 |
47 | @end
--------------------------------------------------------------------------------
/Pod/Classes/LevelsConverter/VOXHistogramLevelsConverter.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 10/9/14.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "VOXHistogramLevelsConverter.h"
28 | #import "macros_blocks.h"
29 |
30 |
31 | static NSUInteger const averagingWindow = 3;
32 |
33 |
34 |
35 | @implementation VOXHistogramLevelsConverter
36 |
37 |
38 | #pragma mark - Public
39 |
40 | - (void)updateLevels:(NSArray *)levels
41 | {
42 | _levels = levels;
43 | }
44 |
45 | - (void)calculateLevelsForSamplingRate:(NSUInteger)samplingRate
46 | completion:(void (^)(NSArray *levels))completion;
47 | {
48 | NSUInteger samplesCount = [self.levels count];
49 |
50 | if (samplingRate == 0 || self.levels == nil) {
51 | safe_block(completion, nil);
52 | }
53 |
54 | if (samplingRate == samplesCount) {
55 | safe_block(completion, self.levels);
56 | return;
57 | }
58 |
59 | if (samplingRate > samplesCount) {
60 | [NSException raise:NSInvalidArgumentException format:@"samplingRate cannot be more than levels count!"];
61 | }
62 |
63 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
64 |
65 | NSMutableArray *result = [NSMutableArray array];
66 | @autoreleasepool {
67 |
68 | CGFloat downSamplingRatio = (CGFloat) samplesCount / samplingRate;
69 | for (NSUInteger i = 1; i <= samplingRate; i ++) {
70 |
71 | NSUInteger windowPosition = (NSUInteger) floorf(i * downSamplingRatio - downSamplingRatio / 2);
72 |
73 | NSInteger windowStart = windowPosition - (NSInteger) floorf(averagingWindow / 2);
74 | NSInteger windowFinish = windowStart + averagingWindow - 1;
75 | NSUInteger windowStartNormalized = (NSUInteger) (windowStart < 0 ? 0 : windowStart);
76 | NSUInteger windowFinishNormalized = windowFinish > (samplesCount - 1) ? samplesCount - 1 : (NSUInteger) windowFinish;
77 | NSRange windowRange = NSMakeRange(windowStartNormalized, windowFinishNormalized - windowStartNormalized + 1);
78 |
79 | NSArray *subArray = [self.levels subarrayWithRange:windowRange];
80 | NSNumber *average = [subArray valueForKeyPath:@"@avg.self"];
81 | [result addObject:average];
82 | }
83 | }
84 |
85 | main_queue_block(completion, [result copy]);
86 | });
87 | }
88 |
89 | @end
--------------------------------------------------------------------------------
/Pod/Classes/ProgressLine/VOXProgressLineView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 23.11.14.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 |
30 |
31 | @interface VOXProgressLineView : UIView
32 |
33 |
34 | /**
35 | * Colors setup
36 | */
37 | @property(nonatomic, strong) IBInspectable UIColor *completeColor;
38 | @property(nonatomic, strong) IBInspectable UIColor *notCompleteColor;
39 | @property(nonatomic, strong) IBInspectable UIColor *downloadedColor;
40 |
41 | /**
42 | * Update current playback progress from 0.0f to 1.0f
43 | */
44 | - (void)updatePlaybackProgress:(CGFloat)playbackProgress;
45 |
46 | /**
47 | * Update current download progress from 0.0f to 1.0f
48 | */
49 | - (void)updateDownloadProgress:(CGFloat)downloadProgress;
50 |
51 | @end
--------------------------------------------------------------------------------
/Pod/Classes/ProgressLine/VOXProgressLineView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 23.11.14.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "VOXProgressLineView.h"
28 |
29 |
30 |
31 | @interface VOXProgressLineView ()
32 |
33 |
34 | @property(nonatomic, assign) CGFloat playbackProgress;
35 | @property(nonatomic, assign) CGFloat downloadProgress;
36 |
37 | @end
38 |
39 |
40 |
41 | @implementation VOXProgressLineView
42 |
43 |
44 | #pragma mark - Init
45 |
46 | - (instancetype)initWithFrame:(CGRect)frame
47 | {
48 | self = [super initWithFrame:frame];
49 | if (self) {
50 | [self setup];
51 | }
52 | return self;
53 | }
54 |
55 | - (id)initWithCoder:(NSCoder *)coder
56 | {
57 | self = [super initWithCoder:coder];
58 | if (self) {
59 | [self setup];
60 | }
61 | return self;
62 | }
63 |
64 | #pragma mark - Setup
65 |
66 | - (void)setup
67 | {
68 | // default colors for debugging
69 | self.notCompleteColor = [UIColor greenColor];
70 | self.completeColor = [UIColor redColor];
71 | self.downloadedColor = [UIColor yellowColor];
72 |
73 | // background should be clear
74 | self.backgroundColor = [UIColor clearColor];
75 | }
76 |
77 | #pragma mark - Public
78 |
79 | - (void)updatePlaybackProgress:(CGFloat)playbackProgress
80 | {
81 | self.playbackProgress = [self _normalizedValue:playbackProgress];
82 | [self setNeedsDisplay];
83 | }
84 |
85 | - (void)updateDownloadProgress:(CGFloat)downloadProgress
86 | {
87 | self.downloadProgress = [self _normalizedDownloadProgressValue:downloadProgress];
88 | [self setNeedsDisplay];
89 | }
90 |
91 | #pragma mark - Drawing
92 |
93 | - (void)drawRect:(CGRect)rect
94 | {
95 | [super drawRect:rect];
96 |
97 | /* Taking graphic context */
98 | CGContextRef context = UIGraphicsGetCurrentContext();
99 |
100 | /* Please, no antialiasing */
101 | CGContextSetShouldAntialias(context, NO);
102 |
103 | // Setting line width
104 | CGContextSetLineWidth(context, rect.size.height);
105 |
106 | // calculate slider line Y position
107 | CGFloat yPosition = rect.size.height / 2;
108 |
109 | // get current rect width
110 | CGFloat rectWidth = rect.size.width;
111 |
112 |
113 |
114 | /* Drawing complete part of slider */
115 |
116 | // setting line color
117 | CGContextSetStrokeColorWithColor(context, self.completeColor.CGColor);
118 |
119 | // start to draw line from left
120 | CGContextMoveToPoint(context, 0, yPosition);
121 |
122 | // calculating line width for current cursor position
123 | CGFloat lineWidth = self.playbackProgress * rectWidth;
124 |
125 | // drawing line with calculated width
126 | CGContextAddLineToPoint(context, lineWidth, yPosition);
127 |
128 | // draw stroke
129 | CGContextStrokePath(context);
130 |
131 |
132 |
133 | /* Drawing downloaded part of slider */
134 |
135 | if (self.downloadProgress > self.playbackProgress) {
136 |
137 | // move ahead
138 | CGContextMoveToPoint(context, lineWidth, yPosition);
139 |
140 | // setting line color
141 | CGContextSetStrokeColorWithColor(context, self.downloadedColor.CGColor);
142 |
143 | // calculating line width for current downloaded position
144 | lineWidth = self.downloadProgress * rectWidth;
145 |
146 | // drawing line with calculated width
147 | CGContextAddLineToPoint(context, lineWidth, yPosition);
148 |
149 | // draw stroke
150 | CGContextStrokePath(context);
151 | }
152 |
153 |
154 |
155 | /* Drawing not complete part of slider */
156 |
157 | // setting line color
158 | CGContextSetStrokeColorWithColor(context, self.notCompleteColor.CGColor);
159 |
160 | // move ahead
161 | CGContextMoveToPoint(context, lineWidth, yPosition);
162 |
163 | // calculating line width for current downloaded position
164 | lineWidth = rectWidth;
165 |
166 | // drawing line with calculated width
167 | CGContextAddLineToPoint(context, lineWidth, yPosition);
168 |
169 | // draw stroke
170 | CGContextStrokePath(context);
171 | }
172 |
173 | #pragma mark - Helpers
174 |
175 | - (CGFloat)_normalizedValue:(CGFloat)value
176 | {
177 | return MAX(MIN(value, 1), 0);
178 | }
179 |
180 | - (CGFloat)_normalizedDownloadProgressValue:(CGFloat)downloadProgressValue
181 | {
182 | return MAX(MIN(downloadProgressValue, 1), self.playbackProgress);
183 | }
184 |
185 | @end
--------------------------------------------------------------------------------
/Pod/Classes/Rendering/VOXHistogramRenderer.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 09.01.15.
3 | // Copyright (c) 2015 Alterplay. All rights reserved.
4 | //
5 |
6 | #import
7 | #import
8 |
9 | @class VOXHistogramRenderingConfiguration;
10 |
11 |
12 |
13 | @interface VOXHistogramRenderer : NSObject
14 |
15 |
16 | #pragma mark - Init
17 | - (instancetype)initWithRenderingConfiguration:(VOXHistogramRenderingConfiguration *)renderingConfiguration NS_DESIGNATED_INITIALIZER;
18 | + (instancetype)rendererWithRenderingConfiguration:(VOXHistogramRenderingConfiguration *)renderingConfiguration;
19 |
20 |
21 | #pragma mark - Rendering
22 | /**
23 | * Will render histogram image on background
24 | *
25 | * @param levels - array of NSNumbers from @0.0f to @1.0f
26 | * @param completion - block will be called when finished rendering
27 | */
28 | - (void)renderHistogramWithLevels:(NSArray *)levels
29 | completion:(void (^)(UIImage *image))completion;
30 |
31 |
32 | #pragma mark - Canceling
33 | /**
34 | * Cancel any rendering process
35 | */
36 | - (void)cancelCurrentRendering;
37 |
38 | @end
39 |
40 |
41 |
42 | @interface VOXHistogramRenderer (Unavailable)
43 |
44 |
45 | - (instancetype)init NS_UNAVAILABLE;
46 | + (instancetype)new NS_UNAVAILABLE;
47 |
48 | @end
--------------------------------------------------------------------------------
/Pod/Classes/Rendering/VOXHistogramRenderer.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 09.01.15.
3 | // Copyright (c) 2015 Alterplay. All rights reserved.
4 | //
5 |
6 | #import "VOXHistogramRenderer.h"
7 | #import "VOXHistogramRenderingOperation.h"
8 | #import "VOXHistogramRenderingConfiguration.h"
9 |
10 |
11 |
12 | @interface VOXHistogramRenderer ()
13 |
14 |
15 | @property(nonatomic, strong) NSOperationQueue *renderingQueue;
16 | @property(nonatomic, strong) VOXHistogramRenderingConfiguration *renderingConfiguration;
17 |
18 | @end
19 |
20 |
21 |
22 | @implementation VOXHistogramRenderer
23 |
24 |
25 | #pragma mark - Init
26 |
27 | - (instancetype)initWithRenderingConfiguration:(VOXHistogramRenderingConfiguration *)renderingConfiguration
28 | {
29 | self = [super init];
30 | if (self) {
31 | self.renderingConfiguration = renderingConfiguration;
32 |
33 | // queue setup
34 | self.renderingQueue = [NSOperationQueue new];
35 | }
36 | return self;
37 | }
38 |
39 | + (instancetype)rendererWithRenderingConfiguration:(VOXHistogramRenderingConfiguration *)renderingConfiguration
40 | {
41 | return [[self alloc] initWithRenderingConfiguration:renderingConfiguration];
42 | }
43 |
44 | #pragma mark - Rendering
45 |
46 | - (void)renderHistogramWithLevels:(NSArray *)levels
47 | completion:(void (^)(UIImage *image))completion
48 | {
49 | NSParameterAssert(levels);
50 | NSParameterAssert(completion);
51 |
52 | /* Cancel previous operation if any */
53 | [self.renderingQueue cancelAllOperations];
54 |
55 | /* Creating rendering operation */
56 | VOXHistogramRenderingOperation *renderingOperation;
57 | renderingOperation = [VOXHistogramRenderingOperation operationWithLevels:levels
58 | renderingConfiguration:self.renderingConfiguration];
59 | renderingOperation.completion = completion;
60 |
61 | /* Run operation on rendering queue */
62 | [self.renderingQueue addOperation:renderingOperation];
63 | }
64 |
65 | #pragma mark - Canceling
66 |
67 | - (void)cancelCurrentRendering
68 | {
69 | [self.renderingQueue cancelAllOperations];
70 | }
71 |
72 | @end
--------------------------------------------------------------------------------
/Pod/Classes/Rendering/VOXHistogramRenderingOperation.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 09.01.15.
3 | // Copyright (c) 2015 Alterplay. All rights reserved.
4 | //
5 |
6 | #import
7 | #import
8 |
9 | @class VOXHistogramRenderingConfiguration;
10 |
11 |
12 |
13 | @interface VOXHistogramRenderingOperation : NSOperation
14 |
15 |
16 | #pragma mark - Completion
17 | /**
18 | * Block will be called when finished rendering
19 | */
20 | @property(nonatomic, copy) void (^completion)(UIImage *image);
21 |
22 | #pragma mark - Rendered Image
23 | /**
24 | * Rendered image, nil until operation is finished
25 | */
26 | @property(nonatomic, strong, readonly) UIImage *image;
27 |
28 |
29 | #pragma mark - Init
30 | - (instancetype)initWithLevels:(NSArray *)levels
31 | renderingConfiguration:(VOXHistogramRenderingConfiguration *)renderingConfiguration NS_DESIGNATED_INITIALIZER;
32 | + (instancetype)operationWithLevels:(NSArray *)levels
33 | renderingConfiguration:(VOXHistogramRenderingConfiguration *)renderingConfiguration;
34 |
35 |
36 | @end
37 |
38 |
39 |
40 | @interface VOXHistogramRenderingOperation (Unavailable)
41 |
42 |
43 | - (instancetype)init NS_UNAVAILABLE;
44 | + (instancetype)new NS_UNAVAILABLE;
45 |
46 | @end
--------------------------------------------------------------------------------
/Pod/Classes/Rendering/VOXHistogramRenderingOperation.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 09.01.15.
3 | // Copyright (c) 2015 Alterplay. All rights reserved.
4 | //
5 |
6 | #import "VOXHistogramRenderingOperation.h"
7 | #import "macros_blocks.h"
8 | #import "VOXHistogramRenderingConfiguration.h"
9 |
10 |
11 |
12 | @interface VOXHistogramRenderingOperation ()
13 |
14 |
15 | @property(nonatomic, strong, readwrite) UIImage *image;
16 | @property(nonatomic, copy) NSArray *levels;
17 | @property(nonatomic, strong) VOXHistogramRenderingConfiguration *renderingConfiguration;
18 |
19 | @end
20 |
21 |
22 |
23 | @implementation VOXHistogramRenderingOperation
24 |
25 |
26 | #pragma mark - Init
27 |
28 | - (instancetype)initWithLevels:(NSArray *)levels
29 | renderingConfiguration:(VOXHistogramRenderingConfiguration *)renderingConfiguration
30 | {
31 | NSParameterAssert(levels);
32 | NSParameterAssert(renderingConfiguration);
33 |
34 | self = [super init];
35 | if (self) {
36 | self.levels = levels;
37 | self.renderingConfiguration = renderingConfiguration;
38 | }
39 | return self;
40 | }
41 |
42 | + (instancetype)operationWithLevels:(NSArray *)levels
43 | renderingConfiguration:(VOXHistogramRenderingConfiguration *)renderingConfiguration
44 | {
45 | return [[self alloc] initWithLevels:levels renderingConfiguration:renderingConfiguration];
46 | }
47 |
48 | #pragma mark - NSOperation
49 |
50 | - (void)main
51 | {
52 | if ([self isCancelled]) {
53 | return;
54 | }
55 |
56 | NSArray *levels = self.levels;
57 | UIImage *renderedImage = [self renderedHistogramWithLevels:levels];
58 |
59 | if ([self isCancelled]) {
60 | return;
61 | }
62 |
63 | self.image = renderedImage;
64 |
65 | // call completion block with result
66 | main_queue_block(self.completion, self.image);
67 | }
68 |
69 | #pragma mark - Rendering
70 |
71 | - (UIImage *)renderedHistogramWithLevels:(NSArray *)levels
72 | {
73 | /* Get image size */
74 | CGSize outputImageSize = self.renderingConfiguration.outputImageSize;
75 |
76 | /* Creating image context */
77 | UIGraphicsBeginImageContextWithOptions(outputImageSize, NO, [self scale]);
78 | CGContextRef context = UIGraphicsGetCurrentContext();
79 |
80 | /* Please, no antialiasing */
81 | CGContextSetShouldAntialias(context, NO);
82 |
83 | [levels enumerateObjectsUsingBlock:^(NSNumber *levelNumber, NSUInteger idx, BOOL *stop) {
84 | /* Check operation is cancelled */
85 | if ([self isCancelled]) {
86 | *stop = YES;
87 | return;
88 | }
89 |
90 | /* Get float from NSNumber */
91 | CGFloat levelFloat = [levelNumber floatValue];
92 |
93 | /* Calculate current peak offset */
94 | CGFloat peakOffset = idx * ([self onePeakWidth] + [self marginWidth]);
95 |
96 | /* Draw every line for peak width */
97 | for (int i = 0; i < [self linesCountInOnePeak]; i ++) {
98 |
99 | /* Calculate current line offset */
100 | CGFloat lineOffset = peakOffset + i * [self lineMinimumWidth];
101 |
102 | /* Get current line color */
103 | UIColor *lineColor = self.renderingConfiguration.peaksColor;
104 |
105 | CGRect rect = CGRectMake(0.0f, 0.0f, outputImageSize.width, outputImageSize.height);
106 |
107 | /* Lets draw */
108 | [self drawLineInContext:context
109 | inRect:rect
110 | withLeftOffset:lineOffset
111 | andWidth:[self lineMinimumWidth]
112 | andLevel:levelFloat
113 | andColor:lineColor];
114 | }
115 | }];
116 |
117 | /* Check operation is cancelled */
118 | if ([self isCancelled]) {
119 | /* Context clean up */
120 | UIGraphicsEndImageContext();
121 | return nil;
122 | }
123 |
124 | /* Get result image from context */
125 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
126 |
127 | /* Context clean up */
128 | UIGraphicsEndImageContext();
129 |
130 | /* Return image in current rendering mode */
131 | return [image imageWithRenderingMode:self.renderingConfiguration.renderingMode];
132 | }
133 |
134 | - (void)drawLineInContext:(CGContextRef)context
135 | inRect:(CGRect)rect
136 | withLeftOffset:(CGFloat)leftOffset
137 | andWidth:(CGFloat)width
138 | andLevel:(CGFloat)level
139 | andColor:(UIColor *)color
140 | {
141 | // Set line color
142 | CGContextSetStrokeColorWithColor(context, color.CGColor);
143 |
144 | // Set line width
145 | CGContextSetLineWidth(context, width);
146 |
147 | // Maybe this will make lines beautiful, but i'm not sure
148 | CGContextSetLineCap(context, kCGLineCapButt);
149 |
150 | // Get current rect height
151 | CGFloat rectHeight = CGRectGetHeight(rect);
152 |
153 | // start to draw line at bottom point
154 | CGContextMoveToPoint(context, leftOffset, rectHeight);
155 |
156 | // calculating line height for level
157 | CGFloat lineHeight = floorf(level * rectHeight);
158 |
159 | // drawing line with calculated height
160 | CGContextAddLineToPoint(context, leftOffset, rectHeight - lineHeight);
161 |
162 | // draw stroke
163 | CGContextStrokePath(context);
164 | }
165 |
166 | #pragma mark - Helpers
167 |
168 | - (CGFloat)lineMinimumWidth
169 | {
170 | return 1 / [self scale];
171 | }
172 |
173 | - (CGFloat)onePeakWidth
174 | {
175 | return [self lineMinimumWidth] * self.renderingConfiguration.peakWidth;
176 | }
177 |
178 | - (CGFloat)marginWidth
179 | {
180 | return [self lineMinimumWidth] * self.renderingConfiguration.marginWidth;
181 | }
182 |
183 | - (NSUInteger)linesCountInOnePeak
184 | {
185 | return (NSUInteger) ([self onePeakWidth] / [self lineMinimumWidth]);
186 | }
187 |
188 | - (CGFloat)scale
189 | {
190 | return [UIScreen mainScreen].scale;
191 | }
192 |
193 | @end
--------------------------------------------------------------------------------
/Pod/Classes/VOXHistogramControlView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 10/21/14.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 | @class VOXHistogramControlView;
30 | @class VOXHistogramView;
31 | @class VOXProgressLineView;
32 |
33 |
34 | typedef NS_ENUM(NSUInteger, VOXHistogramControlViewTrackingMode)
35 | {
36 | VOXHistogramControlViewTrackingModeNone = 0,
37 | VOXHistogramControlViewTrackingModeTap,
38 | VOXHistogramControlViewTrackingModeLongTap
39 | };
40 |
41 |
42 |
43 | @protocol VOXHistogramControlViewDelegate
44 |
45 |
46 | @optional
47 |
48 | /**
49 | * Called when histogram will be shown soon.
50 | */
51 | - (void)histogramControlViewWillShowHistogram:(VOXHistogramControlView *)controlView;
52 |
53 | /**
54 | * Called right after histogram is showed.
55 | */
56 | - (void)histogramControlViewDidShowHistogram:(VOXHistogramControlView *)controlView;
57 |
58 | /**
59 | * Called when histogram will be hidden soon.
60 | */
61 | - (void)histogramControlViewWillHideHistogram:(VOXHistogramControlView *)controlView;
62 |
63 | /**
64 | * Called right after histogram is hidden.
65 | */
66 | - (void)histogramControlViewDidHideHistogram:(VOXHistogramControlView *)controlView;
67 |
68 | /**
69 | * Called when user start tracking.
70 | */
71 | - (void)histogramControlViewDidStartTracking:(VOXHistogramControlView *)controlView;
72 |
73 | /**
74 | * Called when progress changed even if tracking is not finished yet.
75 | */
76 | - (void)histogramControlView:(VOXHistogramControlView *)controlView
77 | didChangeProgress:(CGFloat)progress;
78 |
79 | /**
80 | * Called when user did finish tracking.
81 | */
82 | - (void) histogramControlView:(VOXHistogramControlView *)controlView
83 | didFinishTrackingWithProgress:(CGFloat)progress;
84 |
85 | /**
86 | * Called when user did change scrubbing speed.
87 | */
88 | - (void)histogramControlView:(VOXHistogramControlView *)controlView
89 | didChangeScrubbingSpeed:(CGFloat)scrubbingSpeed;
90 |
91 | /**
92 | * Called when histogram rendering is about to start.
93 | */
94 | - (void)histogramControlViewWillStartRendering:(VOXHistogramControlView *)controlView;
95 |
96 | /**
97 | * Called when histogram rendering finished.
98 | */
99 | - (void)histogramControlViewDidFinishRendering:(VOXHistogramControlView *)controlView;
100 |
101 | @end
102 |
103 |
104 |
105 | @interface VOXHistogramControlView : UIView
106 |
107 |
108 | #pragma mark - Delegate
109 | @property(nonatomic, weak) id delegate;
110 |
111 |
112 | #pragma mark - Managed Views
113 | @property(nonatomic, weak, readonly) VOXHistogramView *histogramView;
114 | @property(nonatomic, weak, readonly) VOXProgressLineView *slider;
115 |
116 |
117 | #pragma mark - Inspectable Properties
118 |
119 | /**
120 | * Peaks colors setup
121 | */
122 | @property(nonatomic, strong) IBInspectable UIColor *completeColor;
123 | @property(nonatomic, strong) IBInspectable UIColor *notCompleteColor;
124 | @property(nonatomic, strong) IBInspectable UIColor *downloadedColor;
125 |
126 | /**
127 | * Width of one peak in pixels (not points!)
128 | */
129 | @property(nonatomic, assign) IBInspectable NSUInteger peakWidth;
130 |
131 | /**
132 | * Margin between two peaks in pixels (not points!)
133 | */
134 | @property(nonatomic, assign) IBInspectable NSUInteger marginWidth;
135 |
136 | /**
137 | * Histogram view height.
138 | *
139 | * @default self.bounds.size.height
140 | */
141 | @property(nonatomic, assign) IBInspectable CGFloat histogramHeight;
142 |
143 | /**
144 | * Height of VOXProgressLineView under histogram.
145 | * If 0.0f then slider will not be created.
146 | *
147 | * @default 0.0f
148 | */
149 | @property(nonatomic, assign) IBInspectable CGFloat sliderHeight;
150 |
151 | /**
152 | * Use scrubbing or not
153 | *
154 | * @default YES
155 | */
156 | @property(nonatomic, assign, readonly) IBInspectable BOOL useScrubbing;
157 |
158 |
159 | #pragma mark - Setup
160 |
161 | /**
162 | * Current tracking mode
163 | *
164 | * VOXHistogramControlViewTrackingModeNone - tracking will be off
165 | * VOXHistogramControlViewTrackingModeTap - tracking will start from tap
166 | * VOXHistogramControlViewTrackingModeLongTap - tracking will start from long tap
167 | *
168 | * @default VOXHistogramControlViewTrackingModeTap
169 | */
170 | @property(nonatomic, assign) VOXHistogramControlViewTrackingMode trackingMode;
171 |
172 |
173 | #pragma mark - State
174 |
175 | /**
176 | * Array of NSNumbers representing histogram levels.
177 | * All values should be between @0.0 and @1.0.
178 | *
179 | * @discussion
180 | * If levels count more than histogram can display in current bounds then levels would be averaged.
181 | * This would be done on background thread. But then rendering process will take more time.
182 | *
183 | * If you do not want to do additional work while rendering histogram then you should always provide
184 | * exact count of levels that histogram can display. To know how much levels you need you should
185 | * use maximumSamplingRate property - it always shows how much levels do you need in current bounds.
186 | */
187 | @property(nonatomic, copy) NSArray *levels;
188 |
189 | /**
190 | * Playback progress value.
191 | */
192 | @property(nonatomic, assign) CGFloat playbackProgress;
193 |
194 | /**
195 | * Download progress value.
196 | */
197 | @property(nonatomic, assign) CGFloat downloadProgress;
198 |
199 | /**
200 | * Returns YES if tracking began.
201 | */
202 | @property(nonatomic, assign, readonly, getter=isTracking) BOOL tracking;
203 |
204 | /**
205 | * Returns YES if histogram currently presented.
206 | */
207 | @property(nonatomic, assign, readonly) BOOL histogramPresented;
208 |
209 | /**
210 | * Return YES if currently animating histogram show/hide.
211 | */
212 | @property(nonatomic, assign, readonly) BOOL animating;
213 |
214 | /**
215 | * Returns maximum count of samples that histogram can show in current bounds.
216 | * Calculated from peakWidth and marginWidth and bound.size.width.
217 | */
218 | @property(nonatomic, assign, readonly) NSUInteger maximumSamplingRate;
219 |
220 |
221 | #pragma mark - Scrubbing
222 |
223 | /**
224 | * Returns current scrubbing speed.
225 | */
226 | @property(nonatomic, assign, readonly) CGFloat scrubbingSpeed;
227 |
228 | /**
229 | * Array of NSNumbers representing scrubbing speeds for different zones.
230 | *
231 | * @example @[ @1.0f, @0.5f, @0.25f, @0.1f ] - this means first zone has 100% speed,
232 | * second zone 50%, and so on.
233 | */
234 | @property(nonatomic, copy) NSArray *scrubbingSpeeds;
235 |
236 | /**
237 | * Array of NSNumbers representing zones when scrubbing speed changes. Every element of array
238 | * means distance by Y from user first touch where tracking began.
239 | *
240 | * @example @[ @0.0f, @50.0f, @100.0f, @150.0f ] - this means scrubbingSpeeds[0] acts
241 | * between 0 and 50pt distance from users touch by Y, scrubbingSpeeds[1] acts between
242 | * 50 and 100pt and so on.
243 | */
244 | @property(nonatomic, copy) NSArray *scrubbingSpeedChangePositions;
245 |
246 |
247 | #pragma mark - Public
248 |
249 | /**
250 | * Show or hide histogram view.
251 | */
252 | - (void)showHistogramViewAnimated:(BOOL)animated;
253 | - (void)hideHistogramViewAnimated:(BOOL)animated;
254 |
255 | /**
256 | * Will stop current histogram rendering if any.
257 | */
258 | - (void)stopHistogramRendering;
259 |
260 | @end
--------------------------------------------------------------------------------
/Pod/Classes/VOXHistogramControlView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 10/21/14.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "VOXHistogramControlView.h"
28 | #import "VOXHistogramView.h"
29 | #import "VOXProgressLineView.h"
30 | #import "VOXHistogramRenderer.h"
31 | #import "VOXHistogramRenderingConfiguration.h"
32 | #import "VOXHistogramLevelsConverter.h"
33 | #import "VOXHistogramAnimator.h"
34 | #import "UIView+Autolayout.h"
35 | #import "FrameAccessor.h"
36 |
37 |
38 |
39 | static NSUInteger const VOXHistogramControlViewDefaultPeakWidth = 3;
40 | static NSUInteger const VOXHistogramControlViewDefaultMarginWidth = 1;
41 |
42 |
43 |
44 | @interface VOXHistogramControlView ()
45 |
46 |
47 | #pragma mark - Public
48 | @property(nonatomic, assign, readwrite, getter=isTracking) BOOL tracking;
49 | @property(nonatomic, assign, readwrite) CGFloat scrubbingSpeed;
50 | @property(nonatomic, assign, readwrite) IBInspectable BOOL useScrubbing;
51 |
52 | #pragma mark - Managed Views
53 | @property(nonatomic, weak, readwrite) VOXHistogramView *histogramView;
54 | @property(nonatomic, weak, readwrite) VOXProgressLineView *slider;
55 |
56 | #pragma mark - Helpers
57 | @property(assign, nonatomic) CGPoint beganTrackingLocation;
58 | @property(assign, nonatomic) CGFloat realPositionValue;
59 | @property(nonatomic, weak) UITouch *currentTouch;
60 |
61 | @property(nonatomic, strong) VOXHistogramRenderer *histogramRenderer;
62 | @property(nonatomic, strong) VOXHistogramAnimator *animator;
63 | @end
64 |
65 |
66 |
67 | @implementation VOXHistogramControlView
68 |
69 |
70 | #pragma mark - Accessors
71 |
72 | - (void)setCompleteColor:(UIColor *)completeColor
73 | {
74 | _completeColor = completeColor;
75 | self.histogramView.completeColor = completeColor;
76 | self.slider.completeColor = completeColor;
77 | }
78 |
79 | - (void)setNotCompleteColor:(UIColor *)notCompleteColor
80 | {
81 | _notCompleteColor = notCompleteColor;
82 | self.histogramView.notCompleteColor = notCompleteColor;
83 | self.slider.notCompleteColor = notCompleteColor;
84 | }
85 |
86 | - (void)setDownloadedColor:(UIColor *)downloadedColor
87 | {
88 | _downloadedColor = downloadedColor;
89 | self.histogramView.downloadedColor = downloadedColor;
90 | self.slider.downloadedColor = downloadedColor;
91 | }
92 |
93 | - (void)setLevels:(NSArray *)levels
94 | {
95 | _levels = [levels copy];
96 | [self _renderHistogram];
97 | }
98 |
99 | - (void)setPlaybackProgress:(CGFloat)playbackProgress
100 | {
101 | if (_playbackProgress == playbackProgress || self.isTracking)
102 | return;
103 |
104 | _playbackProgress = [self _normalizedValue:playbackProgress];
105 |
106 | [self.slider updatePlaybackProgress:playbackProgress];
107 |
108 | if (! self.animator.animating) {
109 | [self.histogramView updatePlaybackProgress:playbackProgress];
110 | }
111 | }
112 |
113 | - (void)setDownloadProgress:(CGFloat)downloadProgress
114 | {
115 | if (_downloadProgress == downloadProgress)
116 | return;
117 |
118 | _downloadProgress = [self _normalizedDownloadProgressValue:downloadProgress];
119 |
120 | [self.slider updateDownloadProgress:downloadProgress];
121 |
122 | if (! self.animator.animating) {
123 | [self.histogramView updateDownloadProgress:downloadProgress];
124 | }
125 | }
126 |
127 | - (BOOL)histogramPresented
128 | {
129 | return self.animator.histogramPresented;
130 | }
131 |
132 | - (BOOL)animating
133 | {
134 | return self.animator.animating;
135 | }
136 |
137 | #pragma mark - Init
138 |
139 | - (id)initWithCoder:(NSCoder *)coder
140 | {
141 | self = [super initWithCoder:coder];
142 | if (self) {
143 | [self setupHistogramView];
144 | [self setupDefaults];
145 | }
146 | return self;
147 | }
148 |
149 | - (instancetype)initWithFrame:(CGRect)frame
150 | {
151 | self = [super initWithFrame:frame];
152 | if (self) {
153 | [self setupHistogramView];
154 | [self setupDefaults];
155 | [self setup];
156 | }
157 | return self;
158 | }
159 |
160 | - (void)awakeFromNib
161 | {
162 | [super awakeFromNib];
163 | [self setup];
164 |
165 | // we should set color to slider here because designable
166 | // properties are set between initWithCoder and awakeFromNib
167 | self.slider.completeColor = self.completeColor;
168 | self.slider.downloadedColor = self.downloadedColor;
169 | self.slider.notCompleteColor = self.notCompleteColor;
170 | }
171 |
172 | #pragma mark - Setup
173 |
174 | - (void)setupDefaults
175 | {
176 | /* No slider by default */
177 | self.sliderHeight = 0.0f;
178 |
179 | /* Use scrubbing */
180 | self.useScrubbing = YES;
181 |
182 | /* Histogram params */
183 | self.peakWidth = VOXHistogramControlViewDefaultPeakWidth;
184 | self.marginWidth = VOXHistogramControlViewDefaultMarginWidth;
185 |
186 | /* Colors */
187 | self.completeColor = [UIColor yellowColor];
188 | self.downloadedColor = [UIColor lightGrayColor];
189 | self.notCompleteColor = [UIColor darkGrayColor];
190 |
191 | /* Scrubbing setup */
192 | self.scrubbingSpeeds = [self _defaultScrubbingSpeeds];
193 | self.scrubbingSpeedChangePositions = [self _defaultScrubbingSpeedChangePositions];
194 | self.scrubbingSpeed = [self.scrubbingSpeeds[0] floatValue];
195 | }
196 |
197 | - (void)setup
198 | {
199 | /* Setup managed views */
200 | [self setupSliderIfNeeded];
201 | [self setupViewsConstraints];
202 |
203 | /* Create animator */
204 | self.animator = [VOXHistogramAnimator animatorWithHistogramView:self.histogramView];
205 | self.animator.delegate = self;
206 |
207 | /* Gesture recognizer setup */
208 | [self setupGestureRecognizer];
209 | }
210 |
211 | - (void)setupHistogramView
212 | {
213 | VOXHistogramView *histogramView = [VOXHistogramView autolayoutView];
214 | [self addSubview:histogramView];
215 | self.histogramView = histogramView;
216 | }
217 |
218 | - (void)setupSliderIfNeeded
219 | {
220 | if (self.sliderHeight > 0) {
221 | VOXProgressLineView *slider = [VOXProgressLineView autolayoutView];
222 | [self addSubview:slider];
223 | self.slider = slider;
224 | }
225 | }
226 |
227 | - (void)setupViewsConstraints
228 | {
229 | VOXHistogramView *histogramView = self.histogramView;
230 |
231 | NSDictionary *histogramBinding = NSDictionaryOfVariableBindings(histogramView);
232 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[histogramView]|"
233 | options:0
234 | metrics:nil
235 | views:histogramBinding]];
236 |
237 | if (self.slider) {
238 | VOXProgressLineView *slider = self.slider;
239 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[slider]|"
240 | options:0
241 | metrics:nil
242 | views:NSDictionaryOfVariableBindings(slider)]];
243 | NSString *format = [NSString stringWithFormat:@"V:[histogramView(%f)][slider(%f)]|", self.histogramHeight, self.sliderHeight];
244 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:format
245 | options:0
246 | metrics:nil
247 | views:NSDictionaryOfVariableBindings(histogramView, slider)]];
248 | }
249 | else {
250 | NSString *format = self.histogramHeight == 0 ? @"V:|[histogramView]|" : [NSString stringWithFormat:@"V:[histogramView(%f)]|",
251 | self.histogramHeight];
252 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:format
253 | options:0
254 | metrics:nil
255 | views:histogramBinding]];
256 | }
257 | }
258 |
259 | - (void)setupGestureRecognizer
260 | {
261 | UILongPressGestureRecognizer *longPressGestureRecognizer;
262 | longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self
263 | action:@selector(tapOccured:)];
264 | longPressGestureRecognizer.delegate = self;
265 | CGFloat pressDuration = self.trackingMode == VOXHistogramControlViewTrackingModeLongTap ? 0.3f : 0.001f;
266 | longPressGestureRecognizer.minimumPressDuration = pressDuration;
267 | [self addGestureRecognizer:longPressGestureRecognizer];
268 | }
269 |
270 | #pragma mark - Public
271 |
272 | - (void)showHistogramViewAnimated:(BOOL)animated
273 | {
274 | [self.animator showHistogramViewAnimated:animated];
275 | }
276 |
277 | - (void)hideHistogramViewAnimated:(BOOL)animated
278 | {
279 | [self.animator hideHistogramViewAnimated:animated];
280 | }
281 |
282 | - (void)stopHistogramRendering
283 | {
284 | [self.histogramRenderer cancelCurrentRendering];
285 | self.histogramRenderer = nil;
286 | }
287 |
288 | #pragma mark - Gestures
289 |
290 | - (void)tapOccured:(UIGestureRecognizer *)sender
291 | {
292 | if (sender.state == UIGestureRecognizerStateBegan) {
293 | [self _notifyDelegateDidStartTracking];
294 | }
295 |
296 | [self _updateValueForCurrentTouch];
297 |
298 | if (sender.state == UIGestureRecognizerStateBegan) {
299 | self.tracking = YES;
300 |
301 | self.beganTrackingLocation = CGPointMake(self.playbackProgress * self.bounds.size.width, self.histogramView.bottom);
302 | self.realPositionValue = self.playbackProgress;
303 | }
304 | else if (sender.state == UIGestureRecognizerStateChanged) {
305 | if (self.useScrubbing) {
306 | [self _updateScrubbingSpeed];
307 | }
308 | }
309 | else if (sender.state == UIGestureRecognizerStateCancelled || sender.state == UIGestureRecognizerStateEnded) {
310 | self.tracking = NO;
311 | self.currentTouch = nil;
312 |
313 | // set default scrubbing speed
314 | self.scrubbingSpeed = [self.scrubbingSpeeds[0] floatValue];
315 |
316 | CGFloat playbackProgress = self.playbackProgress;
317 | [self _notifyDelegateDidFinishTrackingWithValue:playbackProgress];
318 | }
319 | }
320 |
321 | #pragma mark - UIGestureRecognizerDelegate
322 |
323 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
324 | shouldReceiveTouch:(UITouch *)touch
325 | {
326 | self.currentTouch = touch;
327 | return YES;
328 | }
329 |
330 | #pragma mark - VOXHistogramAnimatorDelegate
331 |
332 | - (void)histogramAnimatorWillShowHistogram:(VOXHistogramAnimator *)controlView
333 | {
334 | [self _notifyDelegateWillShowHistogram];
335 | }
336 |
337 | - (void)histogramAnimatorDidShowHistogram:(VOXHistogramAnimator *)controlView
338 | {
339 | [self _notifyDelegateDidShowHistogram];
340 | }
341 |
342 | - (void)histogramAnimatorWillHideHistogram:(VOXHistogramAnimator *)controlView
343 | {
344 | [self _notifyDelegateWillHideHistogram];
345 | }
346 |
347 | - (void)histogramAnimatorDidHideHistogram:(VOXHistogramAnimator *)controlView
348 | {
349 | [self _notifyDelegateDidHideHistogram];
350 | }
351 |
352 | #pragma mark - Helpers
353 |
354 | - (void)_renderHistogram
355 | {
356 | /* Cancel previous rendering */
357 | if (self.histogramRenderer) {
358 | [self.histogramRenderer cancelCurrentRendering];
359 | }
360 |
361 | /* Notify delegate */
362 | [self _notifyDelegateWillStartRendering];
363 |
364 | /* Setup levels converter */
365 | VOXHistogramLevelsConverter *converter = [VOXHistogramLevelsConverter new];
366 | [converter updateLevels:self.levels];
367 |
368 | /* Creating rendering configuration */
369 | VOXHistogramRenderingConfiguration *renderingConfiguration = [VOXHistogramRenderingConfiguration new];
370 | renderingConfiguration.outputImageSize = self.histogramView.bounds.size;
371 | renderingConfiguration.renderingMode = UIImageRenderingModeAlwaysTemplate;
372 | renderingConfiguration.peaksColor = [UIColor whiteColor];
373 | renderingConfiguration.peakWidth = self.peakWidth;
374 | renderingConfiguration.marginWidth = self.marginWidth;
375 |
376 | /* Calculate number of levels that histogram can display in current bounds */
377 | NSUInteger samplingRate = [self _samplingRateForHistogramWidth:CGRectGetWidth(self.histogramView.bounds)
378 | peakWidth:self.peakWidth
379 | marginWidth:self.marginWidth];
380 |
381 | /* Creating histogram renderer */
382 | self.histogramRenderer = [VOXHistogramRenderer rendererWithRenderingConfiguration:renderingConfiguration];
383 |
384 | /* Rendering histogram image */
385 | [converter calculateLevelsForSamplingRate:samplingRate completion:^(NSArray *levelsResampled) {
386 | [self.histogramRenderer renderHistogramWithLevels:levelsResampled completion:^(UIImage *image) {
387 | self.histogramView.image = image;
388 |
389 | /* Notify delegate */
390 | [self _notifyDelegateDidFinishRendering];
391 | }];
392 | }];
393 | }
394 |
395 | - (void)_updateValueForCurrentTouch
396 | {
397 | /* Get touch params */
398 | CGPoint previousLocation = [self.currentTouch previousLocationInView:self];
399 | CGPoint currentLocation = [self.currentTouch locationInView:self];
400 |
401 | CGFloat trackingOffset = currentLocation.x - previousLocation.x;
402 | CGFloat controlViewWidth = CGRectGetWidth(self.bounds);
403 |
404 | self.realPositionValue = self.realPositionValue + (trackingOffset / controlViewWidth);
405 |
406 | CGFloat valueAdjustment = self.scrubbingSpeed * (trackingOffset / controlViewWidth);
407 |
408 | CGFloat thumbAdjustment = 0.0f;
409 |
410 | /* Vertical progress adjustment - when user moves finger down closer to histogram we should also adjust progress */
411 | if (((self.beganTrackingLocation.y < currentLocation.y) && (currentLocation.y < previousLocation.y)) ||
412 | ((self.beganTrackingLocation.y > currentLocation.y) && (currentLocation.y > previousLocation.y))) {
413 | // We are getting closer to the slider, go closer to the real location
414 | thumbAdjustment = (self.realPositionValue - self.playbackProgress) / (1 + fabs(currentLocation.y - self.beganTrackingLocation.y));
415 | }
416 |
417 | if ((trackingOffset == 0 && (currentLocation.y - previousLocation.y) == 0) || ! self.useScrubbing) {
418 | _playbackProgress = currentLocation.x / controlViewWidth;
419 | }
420 | else {
421 | _playbackProgress += valueAdjustment + thumbAdjustment; // should not call setter here
422 | }
423 |
424 | [self.slider updatePlaybackProgress:self.playbackProgress];
425 | [self.histogramView updatePlaybackProgress:self.playbackProgress];
426 |
427 | [self _notifyDelegateDidChangePlaybackProgress:self.playbackProgress];
428 | }
429 |
430 | - (void)_updateScrubbingSpeed
431 | {
432 | CGPoint touchLocation = [self.currentTouch locationInView:self];
433 | CGFloat verticalOffset = ABS(touchLocation.y - self.beganTrackingLocation.y);
434 | NSUInteger scrubbingSpeedChangePosIndex = [self _indexOfLowerScrubbingSpeed:self.scrubbingSpeedChangePositions
435 | forOffset:verticalOffset];
436 | if (scrubbingSpeedChangePosIndex == NSNotFound) {
437 | scrubbingSpeedChangePosIndex = [self.scrubbingSpeeds count];
438 | }
439 |
440 | CGFloat scrubbingSpeed = [self.scrubbingSpeeds[scrubbingSpeedChangePosIndex - 1] floatValue];
441 |
442 | if (scrubbingSpeed != self.scrubbingSpeed) {
443 | self.scrubbingSpeed = scrubbingSpeed;
444 | [self _notifyDelegateDidChangeScrubbingSpeed:scrubbingSpeed];
445 | }
446 | }
447 |
448 | - (NSArray *)_defaultScrubbingSpeeds
449 | {
450 | return @[ @1.0f, @0.5f, @0.25f, @0.1f ];
451 | }
452 |
453 | - (NSArray *)_defaultScrubbingSpeedChangePositions
454 | {
455 | return @[ @0.0f, @50.0f, @100.0f, @150.0f ];
456 | }
457 |
458 | // Return the lowest index in the array of numbers passed in scrubbingSpeedPositions
459 | // whose value is smaller than verticalOffset.
460 | - (NSUInteger)_indexOfLowerScrubbingSpeed:(NSArray *)scrubbingSpeedPositions
461 | forOffset:(CGFloat)verticalOffset
462 | {
463 | for (NSUInteger i = 0; i < [scrubbingSpeedPositions count]; i ++) {
464 | NSNumber *scrubbingSpeedOffset = scrubbingSpeedPositions[i];
465 | if (verticalOffset < [scrubbingSpeedOffset floatValue]) {
466 | return i;
467 | }
468 | }
469 | return NSNotFound;
470 | }
471 |
472 | - (NSUInteger)_samplingRateForHistogramWidth:(CGFloat)histogramWidth
473 | peakWidth:(CGFloat)peakWidth
474 | marginWidth:(CGFloat)marginWidth
475 | {
476 | CGFloat scale = [UIScreen mainScreen].scale;
477 | return (NSUInteger) ceilf((histogramWidth / (peakWidth + marginWidth)) * scale);
478 | }
479 |
480 | - (CGFloat)_normalizedValue:(CGFloat)value
481 | {
482 | return MAX(MIN(value, 1), 0);
483 | }
484 |
485 | - (CGFloat)_normalizedDownloadProgressValue:(CGFloat)downloadProgressValue
486 | {
487 | return MAX(MIN(downloadProgressValue, 1), self.playbackProgress);
488 | }
489 |
490 | #pragma mark - Delegate Notifications
491 |
492 | - (void)_notifyDelegateWillStartRendering
493 | {
494 | if ([self.delegate respondsToSelector:@selector(histogramControlViewWillStartRendering:)]) {
495 | [self.delegate histogramControlViewWillStartRendering:self];
496 | }
497 | }
498 |
499 | - (void)_notifyDelegateDidFinishRendering
500 | {
501 | if ([self.delegate respondsToSelector:@selector(histogramControlViewDidFinishRendering:)]) {
502 | [self.delegate histogramControlViewDidFinishRendering:self];
503 | }
504 | }
505 |
506 | - (void)_notifyDelegateDidStartTracking
507 | {
508 | if ([self.delegate respondsToSelector:@selector(histogramControlViewDidStartTracking:)]) {
509 | [self.delegate histogramControlViewDidStartTracking:self];
510 | }
511 | }
512 |
513 | - (void)_notifyDelegateDidFinishTrackingWithValue:(CGFloat)playbackProgress
514 | {
515 | if ([self.delegate respondsToSelector:@selector(histogramControlView:didFinishTrackingWithProgress:)]) {
516 | [self.delegate histogramControlView:self
517 | didFinishTrackingWithProgress:playbackProgress];
518 | }
519 | }
520 |
521 | - (void)_notifyDelegateDidChangeScrubbingSpeed:(CGFloat)scrubbingSpeed
522 | {
523 | if ([self.delegate respondsToSelector:@selector(histogramControlView:didChangeScrubbingSpeed:)]) {
524 | [self.delegate histogramControlView:self
525 | didChangeScrubbingSpeed:scrubbingSpeed];
526 | }
527 | }
528 |
529 | - (void)_notifyDelegateWillShowHistogram
530 | {
531 | if ([self.delegate respondsToSelector:@selector(histogramControlViewWillShowHistogram:)]) {
532 | [self.delegate histogramControlViewWillShowHistogram:self];
533 | }
534 | }
535 |
536 | - (void)_notifyDelegateDidShowHistogram
537 | {
538 | if ([self.delegate respondsToSelector:@selector(histogramControlViewDidShowHistogram:)]) {
539 | [self.delegate histogramControlViewDidShowHistogram:self];
540 | }
541 | }
542 |
543 | - (void)_notifyDelegateWillHideHistogram
544 | {
545 | if ([self.delegate respondsToSelector:@selector(histogramControlViewWillHideHistogram:)]) {
546 | [self.delegate histogramControlViewWillHideHistogram:self];
547 | }
548 | }
549 |
550 | - (void)_notifyDelegateDidHideHistogram
551 | {
552 | if ([self.delegate respondsToSelector:@selector(histogramControlViewDidHideHistogram:)]) {
553 | [self.delegate histogramControlViewDidHideHistogram:self];
554 | }
555 | }
556 |
557 | - (void)_notifyDelegateDidChangePlaybackProgress:(CGFloat)playbackProgress
558 | {
559 | if ([self.delegate respondsToSelector:@selector(histogramControlView:didChangeProgress:)]) {
560 | [self.delegate histogramControlView:self
561 | didChangeProgress:playbackProgress];
562 | }
563 | }
564 |
565 | @end
--------------------------------------------------------------------------------
/Pod/Classes/VOXHistogramView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 10/8/14.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 |
30 |
31 | @interface VOXHistogramView : UIView
32 |
33 | /**
34 | * Colors setup
35 | */
36 | @property(nonatomic, strong) IBInspectable UIColor *completeColor;
37 | @property(nonatomic, strong) IBInspectable UIColor *notCompleteColor;
38 | @property(nonatomic, strong) IBInspectable UIColor *downloadedColor;
39 |
40 | /**
41 | * Histogram image
42 | */
43 | @property(nonatomic, strong) UIImage *image;
44 |
45 | /**
46 | * Update current playback progress from 0.0f to 1.0f
47 | */
48 | - (void)updatePlaybackProgress:(CGFloat)playbackProgress;
49 |
50 | /**
51 | * Update current download progress from 0.0f to 1.0f
52 | */
53 | - (void)updateDownloadProgress:(CGFloat)downloadProgress;
54 |
55 | @end
--------------------------------------------------------------------------------
/Pod/Classes/VOXHistogramView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Nickolay Sheika on 10/8/14.
3 | // Copyright (c) 2014 Coppertino Inc. All rights reserved. (http://coppertino.com/)
4 | //
5 | // VOX, VOX Player, LOOP for VOX are registered trademarks of Coppertino Inc in US.
6 | // Coppertino Inc. 910 Foulk Road, Suite 201, Wilmington, County of New Castle, DE, 19803, USA.
7 | // Contact phone: +1 (888) 765-7069
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 |
28 | #import "VOXHistogramView.h"
29 | #import "FrameAccessor.h"
30 |
31 |
32 | @interface VOXHistogramView ()
33 |
34 |
35 | @property(nonatomic, assign) CGFloat playbackProgress;
36 | @property(nonatomic, assign) CGFloat downloadProgress;
37 |
38 | @property(nonatomic, weak) UIImageView *completeImageView;
39 | @property(nonatomic, weak) UIImageView *notCompleteImageView;
40 | @property(nonatomic, weak) UIImageView *downloadedImageView;
41 |
42 | @end
43 |
44 |
45 |
46 | @implementation VOXHistogramView
47 |
48 |
49 | #pragma mark - Accessors
50 |
51 | - (void)setCompleteColor:(UIColor *)completeColor
52 | {
53 | _completeColor = completeColor;
54 | self.completeImageView.tintColor = completeColor;
55 | }
56 |
57 | - (void)setNotCompleteColor:(UIColor *)notCompleteColor
58 | {
59 | _notCompleteColor = notCompleteColor;
60 | self.notCompleteImageView.tintColor = notCompleteColor;
61 | }
62 |
63 | - (void)setDownloadedColor:(UIColor *)downloadedColor
64 | {
65 | _downloadedColor = downloadedColor;
66 | self.downloadedImageView.tintColor = downloadedColor;
67 | }
68 |
69 | #pragma mark - Init
70 |
71 | - (instancetype)initWithFrame:(CGRect)frame
72 | {
73 | self = [super initWithFrame:frame];
74 | if (self) {
75 | [self setup];
76 | }
77 | return self;
78 | }
79 |
80 | - (instancetype)initWithCoder:(NSCoder *)coder
81 | {
82 | self = [super initWithCoder:coder];
83 | if (self) {
84 | [self setup];
85 | }
86 | return self;
87 | }
88 |
89 | - (instancetype)init
90 | {
91 | return [self initWithFrame:CGRectZero];
92 | }
93 |
94 | #pragma mark - Layout
95 |
96 | - (void)layoutSubviews
97 | {
98 | [super layoutSubviews];
99 |
100 | self.notCompleteImageView.frame = self.bounds;
101 | self.downloadedImageView.frame = self.bounds;
102 | self.completeImageView.frame = self.bounds;
103 |
104 | CGFloat currentWidth = CGRectGetWidth(self.bounds);
105 | self.completeImageView.width = currentWidth * self.playbackProgress;
106 | self.downloadedImageView.width = currentWidth * self.downloadProgress;
107 | }
108 |
109 | #pragma mark - Setup
110 |
111 | - (void)setup
112 | {
113 | self.notCompleteImageView = [self _buildImageView];
114 | self.downloadedImageView = [self _buildImageView];
115 | self.completeImageView = [self _buildImageView];
116 | }
117 |
118 | - (UIImageView *)_buildImageView
119 | {
120 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
121 | imageView.clipsToBounds = YES;
122 | imageView.contentMode = UIViewContentModeLeft;
123 | [self addSubview:imageView];
124 | return imageView;
125 | }
126 |
127 | #pragma mark - Accessors
128 |
129 | - (void)setImage:(UIImage *)image
130 | {
131 | if ([_image isEqual:image])
132 | return;
133 |
134 | _image = image;
135 |
136 | self.completeImageView.image = image;
137 | self.notCompleteImageView.image = image;
138 | self.downloadedImageView.image = image;
139 |
140 | [self setNeedsLayout];
141 | }
142 |
143 | #pragma mark - Public
144 |
145 | - (void)updatePlaybackProgress:(CGFloat)playbackProgress
146 | {
147 | self.playbackProgress = [self _normalizedValue:playbackProgress];
148 | [self setNeedsLayout];
149 | }
150 |
151 | - (void)updateDownloadProgress:(CGFloat)downloadProgress
152 | {
153 | self.downloadProgress = [self _normalizedDownloadProgressValue:downloadProgress];
154 | [self setNeedsLayout];
155 | }
156 |
157 | #pragma mark - Helpers
158 |
159 | - (CGFloat)_normalizedValue:(CGFloat)value
160 | {
161 | return MAX(MIN(value, 1), 0);
162 | }
163 |
164 | - (CGFloat)_normalizedDownloadProgressValue:(CGFloat)downloadProgressValue
165 | {
166 | return MAX(MIN(downloadProgressValue, 1), self.playbackProgress);
167 | }
168 |
169 | @end
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #VOXHistogramView [](https://travis-ci.org/Coppertino/VOXHistogramView) [](https://github.com/Coppertino/VOXHistogramView) [](https://github.com/Coppertino/VOXHistogramView)
2 |
3 | **The best way to display histogram in your project. Free Software, Hell Yeah!**
4 |
5 | This software is used in our [VOX Player](https://itunes.apple.com/us/app/vox-player/id916215494).
6 |
7 | 
8 |
9 |
10 | ## Usage
11 |
12 | There is two ways how you can use our software.
13 |
14 | ####1. VOXHistogramControlView
15 |
16 | This is a wrapper view over the entire histogram rendering process and playback control.
17 |
18 | - Handles users touches and tells delegate about all events.
19 | - Scrubbing speed support for precise control over audio track rewind.
20 | - Can animate histogram show/hide.
21 | - Controls playback and download progress.
22 | - Controls all histogram rendering process.
23 | - Can display slider view at the bottom of histogram.
24 |
25 | VOXHistogramControlView has full support for autolayout, can be instantiated from storyboard and many params can be setup by IBInspectable properties.
26 |
27 | This is the way we use histogram in our VOX Player project.
28 |
29 |
30 | ```objc
31 |
32 | CGRect frame = /* Build frame… */
33 | VOXHistogramControlView *histogramControlView = [[VOXHistogramControlView alloc] initWithFrame:frame];
34 | histogramControlView.delegate = self;
35 |
36 | NSArray *levels = /* Get levels from API or from player. It should be NSArray of NSNumbers from @0.0 to @1.0. */
37 | histogramControlView.levels = levels;
38 | ```
39 |
40 | ####2. Plain VOXHistogramView.
41 |
42 | If VOXHistogramControlView do not suits your needs you can use all components separately.
43 |
44 | Lets describe them:
45 |
46 | #####VOXHistogramView
47 |
48 | Allows you to display rendered histogram image and provides control over playback progress and download progress. It supports autolayout and can be instantiated from storyboard.
49 |
50 | ```objc
51 | CGRect frame = /* Setup histogram frame */
52 | VOXHistogramView *histogramView = [[VOXHistogramView alloc] initWithFrame:frame];
53 |
54 | UIImage *image = /* Render histogram image */
55 | histogramView.image = image;
56 | ```
57 |
58 | #####VOXHistogramRenderer
59 |
60 | This is main hard worker - it is used to render histogram image from array of levels. Rendering goes in background thread and not blocking the UI.
61 |
62 | ```objc
63 |
64 | VOXHistogramRenderingConfiguration *renderingConfiguration = /* Setup rendering configuration… */
65 |
66 | VOXHistogramRenderer *renderer = [VOXHistogramRenderer rendererWithRenderingConfiguration:renderingConfiguration];
67 |
68 | NSArray *levels = /* Get levels from API or from player. It should be NSArray of NSNumbers from @0.0 to @1.0. */
69 |
70 | [renderer renderHistogramWithLevels:levels completion:^(UIImage *image) {
71 | /* Use histogram image */
72 | }];
73 | ```
74 |
75 | #####VOXHistogramLevelsConverter
76 |
77 | This class allows you to convert levels array in background. For example you have received 1000 levels from API but you need only 300 to display VOXHistogramView in current bounds. So you need to convert those levels by averaging them. This is what VOXHistogramLevelsConverter was created for.
78 |
79 | ```objc
80 | VOXHistogramLevelsConverter *converter = [VOXHistogramLevelsConverter new];
81 |
82 | NSArray *levels = /* Get levels from API or from player… */
83 | [converter updateLevels:levels];
84 |
85 |
86 | NSUInteger samplingRate = /* Calculate number of levels that histogram can display in current bounds */
87 |
88 | /* Convert levels array to sampling rate and render histogram image */
89 | [converter calculateLevelsForSamplingRate:samplingRate completion:^(NSArray *levelsResampled) {
90 | /* Use resampled levels to render histogram image */
91 | }];
92 |
93 | ```
94 |
95 | ###Levels for audio track
96 |
97 | To use our library you should provide array of audio track levels. This is simple NSArray of NSNumbers from @0.0 to @1.0 representing sound level for moment in time. You can get those levels from your audio engine (like BASS) or from API (like Soundcloud).
98 |
99 | How many levels do you need?
100 |
101 | It depends from many parameters like width of one peak, margin between peaks, current VOXHistogramView bounds, device screen scale. For convenience you can use maximumSamplingRate property in VOXHistogramControlView or you should calculate this by yourself if you are using plain VOXHistogramView (take a look in example project).
102 |
103 |
104 |
105 | ## Roadmap
106 |
107 | 1. A lot more unit tests.
108 | 2. Separate pod for VOXHistogramControlView.
109 | 3. Speed improvements in VOXHistogramLevelsConverter.
110 |
111 | ## Example
112 |
113 | To run the example project, clone the repo, and run pod install from the Example directory first.
114 |
115 | ## Requirements
116 |
117 | - iOS 7.1 and higher
118 | - ARC
119 |
120 | ## Installation
121 |
122 | VOXHistogramView is available through [CocoaPods](http://cocoapods.org). To install
123 | it, simply add the following line to your Podfile:
124 |
125 | ```ruby
126 | pod "VOXHistogramView"
127 | ```
128 |
129 | ## Author
130 |
131 | Nickolay Sheika, hawk.ukr@gmail.com
132 |
133 | ## License
134 |
135 | VOXHistogramView is available under the MIT license. See the LICENSE file for more info.
136 | **VOX**, **VOX Player**, **LOOP for VOX** are registered trademarks of Coppertino Inc in US.
137 |
138 |
--------------------------------------------------------------------------------
/VOXHistogramView.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "VOXHistogramView"
3 | s.version = "0.1.0"
4 | s.summary = "The best way to display histogram in your project."
5 | s.homepage = "https://github.com/Coppertino/VOXHistogramView"
6 | s.license = 'MIT'
7 | s.author = { "Nickolay Sheika" => "hawk.ukr@gmail.com" }
8 | s.source = { :git => "https://github.com/Coppertino/VOXHistogramView.git", :tag => s.version.to_s }
9 |
10 | s.platform = :ios, '7.1'
11 | s.requires_arc = true
12 |
13 | s.source_files = 'Pod/Classes/**/*'
14 |
15 | s.dependency 'macros_blocks', '0.0.3'
16 | s.dependency 'FrameAccessor', '2.0'
17 | end
18 |
--------------------------------------------------------------------------------
/_Pods.xcodeproj:
--------------------------------------------------------------------------------
1 | Example/Pods/Pods.xcodeproj
--------------------------------------------------------------------------------