From 5b89950f60ab44e4e94aecf187072f9ade5312f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Thu, 6 Oct 2016 18:18:33 +0300 Subject: [PATCH 01/31] After auto-conversion --- Example/SRC/VideoCollectionViewController.swift | 6 +++--- Example/Waveform.xcodeproj/project.pbxproj | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Example/SRC/VideoCollectionViewController.swift b/Example/SRC/VideoCollectionViewController.swift index 8eea1c1..50677af 100644 --- a/Example/SRC/VideoCollectionViewController.swift +++ b/Example/SRC/VideoCollectionViewController.swift @@ -12,12 +12,12 @@ import Photos @objc class VideoCollectionViewController: UICollectionViewController { - var assetsFetchResults: [PHFetchResult] = [] + var assetsFetchResults: [PHFetchResult] = [PHFetchResult]() var moments: [PHAssetCollection] = [] var userAlbumsFetchPredicate = NSPredicate(format: "estimatedAssetCount > 0") var userAlbumsFetchSortDescriptors = [NSSortDescriptor(key: "startDate", ascending: false)] - var inAlbumItemsFetchPredicate = NSPredicate(format: "mediaType == %d", PHAssetMediaType.Video.rawValue) + var inAlbumItemsFetchPredicate = NSPredicate(format: "mediaType == %d", PHAssetMediaType.video.rawValue) var selectedSnapshotView: UIView? @@ -44,7 +44,7 @@ class VideoCollectionViewController: UICollectionViewController { // MARK: - Constuctor/Destructor required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - PHPhotoLibrary.sharedPhotoLibrary().registerChangeObserver(self) + PHPhotoLibrary.shared().registerChangeObserver(self) } deinit{ diff --git a/Example/Waveform.xcodeproj/project.pbxproj b/Example/Waveform.xcodeproj/project.pbxproj index 7e138b0..b695fec 100644 --- a/Example/Waveform.xcodeproj/project.pbxproj +++ b/Example/Waveform.xcodeproj/project.pbxproj @@ -227,6 +227,8 @@ TargetAttributes = { 8B3F34ED1C243BA6006A4B67 = { CreatedOnToolsVersion = 7.2; + DevelopmentTeam = VVU5C37FM9; + LastSwiftMigration = 0800; }; }; }; @@ -411,11 +413,14 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = VVU5C37FM9; INFOPLIST_FILE = SRC/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = denivip.Waveform; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "SRC/Waveform-Bridging-Header.h"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -425,11 +430,14 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = VVU5C37FM9; INFOPLIST_FILE = SRC/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = denivip.Waveform; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "SRC/Waveform-Bridging-Header.h"; + SWIFT_VERSION = 3.0; }; name = Release; }; From 7c1524d3d6796835b38b5be23022e533aba64c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Mon, 10 Oct 2016 15:26:15 +0300 Subject: [PATCH 02/31] Swift3 migration. Project compiles. But plot not drawing. --- .../SRC/Base.lproj/LaunchScreen.storyboard | 12 +-- Example/SRC/Base.lproj/Main.storyboard | 78 +++++++++---------- Example/SRC/VideoCollectionReusableView.swift | 45 ++++++----- Example/SRC/VideoCollectionViewCell.swift | 14 ++-- .../SRC/VideoCollectionViewController.swift | 71 +++++++++-------- Example/SRC/ViewController.swift | 22 +++--- Source/DVGAudioWaveformDiagram.swift | 56 ++++++------- Source/DVGAudioWaveformDiagramModel.swift | 12 +-- Source/DVGWaveformView.swift | 26 +++---- Source/Data Source/AudioSamplesReader.swift | 70 ++++++++++------- .../ScalableChannelsContainer.swift | 14 ++-- Source/Utility/AudioSamplesContainer.swift | 10 ++- Source/Utility/Buffer.swift | 68 +++++++++------- Source/Utility/Channel.swift | 12 +-- Source/Utility/DiagramGeometry.swift | 14 ++-- Source/Utility/Dispatch.swift | 17 ++-- Source/Utility/Error.swift | 6 +- Source/Utility/LogicProvider.swift | 10 +-- Source/Utility/Protocols.swift | 20 ++--- Source/Utility/UIKit+extensions.swift | 6 +- Source/View Model/ChannelSourceMapper.swift | 6 +- Source/View Model/DiagramModel.swift | 16 ++-- Source/View Model/PlotModel.swift | 2 +- Source/View/Diagram.swift | 14 ++-- Source/View/PlaybackPositionView.swift | 29 +++---- Source/View/Plot.swift | 49 ++++++------ Source/View/SelectionView.swift | 12 +-- 27 files changed, 368 insertions(+), 343 deletions(-) diff --git a/Example/SRC/Base.lproj/LaunchScreen.storyboard b/Example/SRC/Base.lproj/LaunchScreen.storyboard index 2e721e1..93abbb1 100644 --- a/Example/SRC/Base.lproj/LaunchScreen.storyboard +++ b/Example/SRC/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,8 @@ - - + + - + + @@ -13,10 +14,9 @@ - + - - + diff --git a/Example/SRC/Base.lproj/Main.storyboard b/Example/SRC/Base.lproj/Main.storyboard index 012fc2b..e201333 100644 --- a/Example/SRC/Base.lproj/Main.storyboard +++ b/Example/SRC/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - - + + - - + + @@ -15,31 +15,31 @@ - + - - - + + + - - + @@ -50,24 +50,23 @@ - - + - + - - + + @@ -76,30 +75,25 @@ - + - - + - - - - + - + @@ -110,9 +104,8 @@ - - + @@ -131,28 +124,31 @@ - + @@ -168,7 +164,6 @@ - @@ -179,7 +174,6 @@ - diff --git a/Example/SRC/VideoCollectionReusableView.swift b/Example/SRC/VideoCollectionReusableView.swift index 43f9ba0..4777338 100644 --- a/Example/SRC/VideoCollectionReusableView.swift +++ b/Example/SRC/VideoCollectionReusableView.swift @@ -49,7 +49,7 @@ class VideoCollectionReusableView: UICollectionReusableView { } } - let date = NSDateFormatter.localizedStringFromDate(collection.startDate!, dateStyle:.LongStyle, timeStyle:.NoStyle) + let date = DateFormatter.localizedString(from: collection.startDate!, dateStyle:.long, timeStyle:.none) if self.titleLabel.text != nil { self.dateLabel.text = date @@ -76,30 +76,33 @@ class VideoCollectionReusableView: UICollectionReusableView { if (self.subtitleLabel.text?.characters.count == 0) { - self.titleLabel.frame = CGRectMake(horizontalBordersOffset, - titleLabelTopOffsetWithNoSubtitle, - CGRectGetWidth(self.bounds) - dateLabelWidth, - CGRectGetHeight(self.bounds) - titleLabelTopOffsetWithNoSubtitle) + self.titleLabel.frame = CGRect(origin: CGPoint(x: horizontalBordersOffset, + y: titleLabelTopOffsetWithNoSubtitle ), + size: CGSize(width: self.bounds.width - dateLabelWidth, + height: self.bounds.height - titleLabelTopOffsetWithNoSubtitle )) + + + + self.dateLabel.frame = CGRect( origin: CGPoint(x: self.bounds.width - dateLabelWidth - horizontalBordersOffset, + y: 0 + titleLabelTopOffsetWithNoSubtitle ), + size: CGSize(width: dateLabelWidth, + height: self.bounds.height - titleLabelTopOffsetWithNoSubtitle )) - self.dateLabel.frame = CGRectMake(CGRectGetWidth(self.bounds) - dateLabelWidth - horizontalBordersOffset, - 0 + titleLabelTopOffsetWithNoSubtitle, - dateLabelWidth, - CGRectGetHeight(self.bounds) - titleLabelTopOffsetWithNoSubtitle) } else { - self.titleLabel.frame = CGRectMake(horizontalBordersOffset, - titleLabelTopOffset, - CGRectGetWidth(self.bounds) - dateLabelWidth - 2 * horizontalBordersOffset, - CGRectGetHeight(self.titleLabel.bounds)) + self.titleLabel.frame = CGRect( origin: CGPoint(x: horizontalBordersOffset, + y: titleLabelTopOffset ), + size: CGSize(width: self.bounds.width - dateLabelWidth - 2 * horizontalBordersOffset, + height: self.titleLabel.bounds.height )) - self.subtitleLabel.frame = CGRectMake(horizontalBordersOffset, - CGRectGetHeight(self.bounds) - subtitleLabelBottomOffset - CGRectGetHeight(self.subtitleLabel.bounds), - CGRectGetWidth(self.bounds) - dateLabelWidth - 2 * horizontalBordersOffset, - CGRectGetHeight(self.subtitleLabel.bounds)) + self.subtitleLabel.frame = CGRect( origin: CGPoint(x: horizontalBordersOffset, + y: self.bounds.height - subtitleLabelBottomOffset - self.subtitleLabel.bounds.height ), + size: CGSize(width: self.bounds.width - dateLabelWidth - 2 * horizontalBordersOffset, + height: self.subtitleLabel.bounds.height)) - self.dateLabel.frame = CGRectMake(CGRectGetWidth(self.bounds) - dateLabelWidth - horizontalBordersOffset, - titleLabelTopOffset, - dateLabelWidth, - CGRectGetHeight(self.dateLabel.bounds) ) + self.dateLabel.frame = CGRect( origin: CGPoint(x: self.bounds.width - dateLabelWidth - horizontalBordersOffset, + y: titleLabelTopOffset ), + size: CGSize(width: dateLabelWidth, + height: self.dateLabel.bounds.height )) } } } diff --git a/Example/SRC/VideoCollectionViewCell.swift b/Example/SRC/VideoCollectionViewCell.swift index eebe0f0..08d66e4 100644 --- a/Example/SRC/VideoCollectionViewCell.swift +++ b/Example/SRC/VideoCollectionViewCell.swift @@ -20,29 +20,29 @@ class VideoCollectionViewCell: UICollectionViewCell { guard let videoSource = videoSource else { return } - self.timeLabel.text = self.stringWithTime(videoSource.duration) + self.timeLabel.text = self.stringWithTime(time: videoSource.duration) self.timeLabelContainer.layer.cornerRadius = self.timeLabelContainer.bounds.size.height/2; - imageManager.requestImageForAsset(videoSource, targetSize:self.bounds.size, contentMode:.AspectFill, options:nil, resultHandler: {result, _ in + imageManager.requestImage(for: videoSource, targetSize:self.bounds.size, contentMode:.aspectFill, options:nil, resultHandler: {result, _ in self.imageView.image = result; }) } } - func stringWithTime(time:NSTimeInterval) -> String { - var seconds = time; + func stringWithTime(time:TimeInterval) -> String { + var seconds = time.int; var minutes = seconds/60; seconds = seconds%60; let hours = minutes/60; minutes = minutes%60; if hours > 0 { - return String(format: "%d:%02d:%02d", Int(hours), Int(minutes), Int(seconds)); + return String(format: "%d:%d:%d", hours, minutes, seconds); } else if minutes > 0 { - return String(format:"%d:%02d", Int(minutes), Int(seconds)); + return String(format:"%d:%d", minutes, seconds); } else { - return String(format:"0:%02d", Int(seconds)); + return String(format:"0:%d", seconds); } } } diff --git a/Example/SRC/VideoCollectionViewController.swift b/Example/SRC/VideoCollectionViewController.swift index 50677af..adbafed 100644 --- a/Example/SRC/VideoCollectionViewController.swift +++ b/Example/SRC/VideoCollectionViewController.swift @@ -21,7 +21,7 @@ class VideoCollectionViewController: UICollectionViewController { var selectedSnapshotView: UIView? - private struct Constants { + fileprivate struct Constants { static let collectionViewCellReuseId = "video_collection_view_cell" static let collectionHeaderReuseId = "video_collection_view_header" static let collectionFooterReuseId = "FooterView" @@ -44,11 +44,11 @@ class VideoCollectionViewController: UICollectionViewController { // MARK: - Constuctor/Destructor required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - PHPhotoLibrary.shared().registerChangeObserver(self) + PHPhotoLibrary.shared().register(self) } deinit{ - PHPhotoLibrary.sharedPhotoLibrary().unregisterChangeObserver(self) + PHPhotoLibrary.shared().unregisterChangeObserver(self) } // MARK: - View Controller Lifetime @@ -57,10 +57,10 @@ class VideoCollectionViewController: UICollectionViewController { // Hide nav bar bottom line let navBarHairlineImageView: UIImageView? = navigationController?.barHairlineImageView() - navBarHairlineImageView?.hidden = true; + navBarHairlineImageView?.isHidden = true; } - override func viewDidAppear(animated: Bool) { + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) clearApplicationTmpDirectory() @@ -74,17 +74,17 @@ class VideoCollectionViewController: UICollectionViewController { // MARK: - UICollectionViewDataSource extension VideoCollectionViewController { - override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { + override func numberOfSections(in collectionView: UICollectionView) -> Int { return assetsFetchResults.count } - override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return assetsFetchResults[section].count } - override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { + override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let cell = collectionView.dequeueReusableCellWithReuseIdentifier(Constants.collectionViewCellReuseId, forIndexPath:indexPath) + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Constants.collectionViewCellReuseId, for:indexPath) if let cell = cell as? VideoCollectionViewCell, let asset = self.assetsFetchResults[indexPath.section][indexPath.row] as? PHAsset { @@ -96,14 +96,14 @@ extension VideoCollectionViewController { return cell } - override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView { + override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { - let reuseId = Constants.collectionSupplementaryElementReuseIdForKind(kind) - let reusableView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: reuseId, forIndexPath: indexPath) + let reuseId = Constants.collectionSupplementaryElementReuseIdForKind(kind: kind) + let reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: reuseId, for: indexPath) switch (kind, reusableView) { case (UICollectionElementKindSectionHeader, let headerView as VideoCollectionReusableView): - headerView.configureWithCollection(self.moments[indexPath.section]) + headerView.configureWithCollection(collection: self.moments[indexPath.section]) case (UICollectionElementKindSectionFooter, _): () default: fatalError() @@ -119,20 +119,20 @@ extension VideoCollectionViewController: UICollectionViewDelegateFlowLayout { func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { let count = floor(self.view.bounds.width/Constants.preview_width); - let width = CGRectGetWidth(self.view.bounds)/count; - return CGSizeMake(width, Constants.preview_height); + let width = self.view.bounds.width/count; + return CGSize(width: width,height: Constants.preview_height); } func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets { - return UIEdgeInsetsZero + return .zero } } // MARK: - Navigation/Transition extension VideoCollectionViewController { - override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { - let controller = segue.destinationViewController as! ViewController + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + let controller = segue.destination as! ViewController let cell = sender as! VideoCollectionViewCell controller.phAsset = cell.videoSource } @@ -143,30 +143,28 @@ extension VideoCollectionViewController { extension VideoCollectionViewController { func updateAssetsFetchResultsAndMoments() { - var assets = [PHFetchResult]() + var assets = [PHFetchResult]() var moments = [PHAssetCollection]() let userAlbumsFetchOptions = PHFetchOptions() userAlbumsFetchOptions.predicate = userAlbumsFetchPredicate userAlbumsFetchOptions.sortDescriptors = userAlbumsFetchSortDescriptors - let userAlbumsFetchResult = PHAssetCollection.fetchMomentsWithOptions(userAlbumsFetchOptions) + let userAlbumsFetchResult = PHAssetCollection.fetchMoments(with: userAlbumsFetchOptions) let inAlbumItemsFetchOptions = PHFetchOptions() inAlbumItemsFetchOptions.predicate = inAlbumItemsFetchPredicate - userAlbumsFetchResult.enumerateObjectsUsingBlock { (collection, _, _) -> Void in - guard let collection = collection as? PHAssetCollection else { - return - } + + userAlbumsFetchResult.enumerateObjects ({ (collection, _, _) -> Void in - let assetsFetchResult = PHAsset.fetchAssetsInAssetCollection(collection, options: inAlbumItemsFetchOptions) + let assetsFetchResult = PHAsset.fetchAssets(in: collection, options: inAlbumItemsFetchOptions) if assetsFetchResult.count > 0 { - assets.append(assetsFetchResult) + assets.append(assetsFetchResult as! PHFetchResult) moments.append(collection) } - } + }) self.moments = moments self.assetsFetchResults = assets @@ -176,20 +174,21 @@ extension VideoCollectionViewController { // MARK: - View Controller Auto Rotation extension VideoCollectionViewController { - override func shouldAutorotate() -> Bool { + + override var shouldAutorotate: Bool { return false } - override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { - return .Portrait + override var supportedInterfaceOrientations: UIInterfaceOrientationMask { + return .portrait } } // MARK: - PHPhotoLibraryChangeObserver extension VideoCollectionViewController: PHPhotoLibraryChangeObserver { - func photoLibraryDidChange(changeInstance: PHChange) { - dispatch_async(dispatch_get_main_queue()) { () -> Void in + func photoLibraryDidChange(_ changeInstance: PHChange) { + DispatchQueue.main.async { () -> Void in self.updateAssetsFetchResultsAndMoments() self.collectionView?.reloadData() } @@ -208,9 +207,9 @@ extension UINavigationController { // MARK: - UIView ex extension UIView { - func findSubview(predicate: (T) -> (Bool)) -> T? { + func findSubview(_ predicate: (T) -> (Bool)) -> T? { - if let self_ = self as? T where predicate(self_) { + if let self_ = self as? T , predicate(self_) { return self_ } @@ -226,10 +225,10 @@ extension UIView { // MARK: - Utility func clearApplicationTmpDirectory() { do { - let tmpDirectoryContent = try NSFileManager.defaultManager().contentsOfDirectoryAtPath(NSTemporaryDirectory()) + let tmpDirectoryContent = try FileManager.default.contentsOfDirectory(atPath: NSTemporaryDirectory()) for file in tmpDirectoryContent { let filePath = NSTemporaryDirectory() + file - try NSFileManager.defaultManager().removeItemAtPath(filePath) + try FileManager.default.removeItem(atPath: filePath) } } catch (let error) { print("\(#function), catched error:\(error)") diff --git a/Example/SRC/ViewController.swift b/Example/SRC/ViewController.swift index 154f115..b091a99 100644 --- a/Example/SRC/ViewController.swift +++ b/Example/SRC/ViewController.swift @@ -27,15 +27,15 @@ class ViewController: UIViewController, DVGDiagramMovementsDelegate { let options = PHContentEditingInputRequestOptions() options.canHandleAdjustmentData = {_ in return false} - phAsset.requestContentEditingInputWithOptions(options) { contentEditingInput, info in + phAsset.requestContentEditingInput(with: options) { contentEditingInput, info in print(contentEditingInput, info) - dispatch_async(dispatch_get_main_queue()) { + DispatchQueue.main.async { if let asset = contentEditingInput?.avAsset { self.waveform.asset = asset self.configureWaveform() } else { print(info[PHContentEditingInputResultIsInCloudKey]) - if let value = info[PHContentEditingInputResultIsInCloudKey] as? Int where value == 1 { + if let value = info[PHContentEditingInputResultIsInCloudKey] as? Int, value == 1 { self.showAlert("Load video from iCloud first") } else { self.showAlert("Can't get audio from this video.") @@ -46,27 +46,27 @@ class ViewController: UIViewController, DVGDiagramMovementsDelegate { } } - func showAlert(message: String) { - let alert = UIAlertController(title: nil, message: message, preferredStyle: .Alert) - alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil)) - self.presentViewController(alert, animated: true, completion: nil) + func showAlert(_ message: String) { + let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) + self.present(alert, animated: true, completion: nil) } func configureWaveform() { self.waveform.movementDelegate = self let waveform1 = self.waveform.maxValuesWaveform() - waveform1?.lineColor = UIColor.redColor() + waveform1?.lineColor = UIColor.red let waveform2 = self.waveform.avgValuesWaveform() - waveform2?.lineColor = UIColor.greenColor() + waveform2?.lineColor = UIColor.green self.waveform.numberOfPointsOnThePlot = 2000 } - func diagramDidSelect(dataRange: DataRange) { + func diagramDidSelect(_ dataRange: DataRange) { print("\(#function), dataRange: \(dataRange)") } - func diagramMoved(scale scale: Double, start: Double) { + func diagramMoved(scale: Double, start: Double) { print("\(#function), scale: \(scale), start: \(start)") } diff --git a/Source/DVGAudioWaveformDiagram.swift b/Source/DVGAudioWaveformDiagram.swift index e69d627..ef89781 100644 --- a/Source/DVGAudioWaveformDiagram.swift +++ b/Source/DVGAudioWaveformDiagram.swift @@ -99,46 +99,46 @@ class DVGAudioWaveformDiagram: UIView { private var panStartLocation: CGFloat? - func handlePanToSelect(pan: UIPanGestureRecognizer) { + func handlePanToSelect(_ pan: UIPanGestureRecognizer) { switch pan.state { - case .Began: + case .began: if self.panStartLocation == nil { - self.panStartLocation = pan.locationInView(self).x + self.panStartLocation = pan.location(in: self).x } - self.configureSelectionFromPosition(panStartLocation!, toPosition: pan.locationInView(self).x) - case .Failed: + self.configureSelectionFromPosition(panStartLocation!, toPosition: pan.location(in: self).x) + case .failed: print("pan failed") - case .Ended: + case .ended: // notify delegate self.panStartLocation = nil if let selection = self.selection { self.delegate?.diagramDidSelect(selection) } break - case .Changed: - self.configureSelectionFromPosition(panStartLocation!, toPosition: pan.locationInView(self).x) + case .changed: + self.configureSelectionFromPosition(panStartLocation!, toPosition: pan.location(in: self).x) default: break } } - func handleTapToSelect(tap: UILongPressGestureRecognizer) { + func handleTapToSelect(_ tap: UILongPressGestureRecognizer) { switch self.pinch.state { - case .Began, .Changed: + case .began, .changed: return default: break } switch tap.state { - case .Began: - self.panStartLocation = pan.locationInView(self).x - self.configureSelectionFromPosition(tap.locationInView(self).x) - case .Failed: + case .began: + self.panStartLocation = pan.location(in: self).x + self.configureSelectionFromPosition(_startPosition: tap.location(in: self).x) + case .failed: print("tap failed") - case .Ended: - self.configureSelectionFromPosition(tap.locationInView(self).x) + case .ended: + self.configureSelectionFromPosition(_startPosition: tap.location(in: self).x) if let selection = self.selection { self.delegate?.diagramDidSelect(selection) } @@ -146,7 +146,7 @@ class DVGAudioWaveformDiagram: UIView { } } - func handlePinch(gesture: UIPinchGestureRecognizer) { + func handlePinch(_ gesture: UIPinchGestureRecognizer) { self.selectionView.selection = nil let k = self.playbackRelativePosition @@ -156,26 +156,26 @@ class DVGAudioWaveformDiagram: UIView { self.selection = l switch gesture.state { - case .Changed: + case .changed: let scale = gesture.scale - let locationX = gesture.locationInView(gesture.view).x + let locationX = gesture.location(in: gesture.view).x let relativeLocation = locationX/gesture.view!.bounds.width self.delegate?.zoomAt(relativeLocation, relativeScale: scale) gesture.scale = 1.0 - case .Ended: + case .ended: print(self.dataSource?.geometry ) default:() } } - func handlePan(gesture: UIPanGestureRecognizer) { + func handlePan(_ gesture: UIPanGestureRecognizer) { self.selectionView.selection = nil switch gesture.state { - case .Changed: - let deltaX = gesture.translationInView(gesture.view).x + case .changed: + let deltaX = gesture.translation(in: gesture.view).x let relativeDeltaX = deltaX/gesture.view!.bounds.width self.delegate?.moveByDistance(relativeDeltaX) - gesture.setTranslation(.zero, inView: gesture.view) + gesture.setTranslation(.zero, in: gesture.view) default:() } @@ -211,7 +211,7 @@ class DVGAudioWaveformDiagram: UIView { self.configureSelectionFromPosition(_startPosition, toPosition: _startPosition) } - func configureSelectionFromPosition(_startPosition: CGFloat, toPosition _endPosition: CGFloat) { + func configureSelectionFromPosition(_ _startPosition: CGFloat, toPosition _endPosition: CGFloat) { //TODO: move geometry logic to viewModel (create it first) var startPosition = min(_endPosition, _startPosition) @@ -246,10 +246,10 @@ extension DVGAudioWaveformDiagram: UIGestureRecognizerDelegate { } } - override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool { + override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { if gestureRecognizer == self.panToSelect { - self.tapToSelect.enabled = false - self.tapToSelect.enabled = true + self.tapToSelect.isEnabled = false + self.tapToSelect.isEnabled = true } return true } diff --git a/Source/DVGAudioWaveformDiagramModel.swift b/Source/DVGAudioWaveformDiagramModel.swift index e0eefb4..6bda713 100644 --- a/Source/DVGAudioWaveformDiagramModel.swift +++ b/Source/DVGAudioWaveformDiagramModel.swift @@ -10,8 +10,8 @@ import Foundation import UIKit protocol DVGDiagramMovementsDelegate: class { - func diagramDidSelect(dataRange: DataRange) - func diagramMoved(scale scale: Double, start: Double) + func diagramDidSelect(_ dataRange: DataRange) + func diagramMoved(scale: Double, start: Double) } class DVGAudioWaveformDiagramModel: DiagramModel, DVGDiagramDelegate { @@ -20,17 +20,17 @@ class DVGAudioWaveformDiagramModel: DiagramModel, DVGDiagramDelegate { var originalSelection: DataRange? - func diagramDidSelect(dataRange: DataRange) { + func diagramDidSelect(_ dataRange: DataRange) { self.originalSelection = dataRange self.movementsDelegate?.diagramDidSelect(dataRange) } - override func zoom(start start: CGFloat, scale: CGFloat) { + override func zoom(start: CGFloat, scale: CGFloat) { super.zoom(start: start, scale: scale) self.movementsDelegate?.diagramMoved(scale: self.geometry.scale, start: self.geometry.start) } - override func moveToPosition(start: CGFloat) { + override func moveToPosition(_ start: CGFloat) { super.moveToPosition(start) self.movementsDelegate?.diagramMoved(scale: self.geometry.scale, start: self.geometry.start) } -} \ No newline at end of file +} diff --git a/Source/DVGWaveformView.swift b/Source/DVGWaveformView.swift index e0d6a40..0f317ff 100644 --- a/Source/DVGWaveformView.swift +++ b/Source/DVGWaveformView.swift @@ -29,7 +29,7 @@ class DVGWaveformController: NSObject { //MARK: - //MARK: - Configuration //MARK: - Internal configuration - func addPlotViewToContainerView(containerView: UIView) { + func addPlotViewToContainerView(_ containerView: UIView) { let diagram = DVGAudioWaveformDiagram() self.diagram = diagram self.diagram.translatesAutoresizingMaskIntoConstraints = false @@ -51,7 +51,7 @@ class DVGWaveformController: NSObject { } //MARK: - For external configuration - func waveformWithIdentifier(identifier: String) -> Plot? { + func waveformWithIdentifier(_ identifier: String) -> Plot? { return self.diagram.waveformDiagramView.plotWithIdentifier(identifier) } @@ -65,7 +65,7 @@ class DVGWaveformController: NSObject { //MARK: - //MARK: - Reading - func readAndDrawSynchronously(completion: (ErrorType?) -> ()) { + func readAndDrawSynchronously(_ completion: @escaping (Error?) -> ()) { if self.samplesReader == nil { completion(NSError(domain: "",code: -1, userInfo: nil)) @@ -91,17 +91,17 @@ class DVGWaveformController: NSObject { } } - func addDataSource(dataSource: ChannelSource) { + func addDataSource(_ dataSource: ChannelSource) { channelSourceMapper.addChannelSource(dataSource) } //MARK: - //MARK: - Private vars - private var diagram: DVGAudioWaveformDiagram! - private var diagramViewModel = DVGAudioWaveformDiagramModel() - private var samplesReader: AudioSamplesReader! - private var waveformDataSource = ScalableChannelsContainer() - private var channelSourceMapper = ChannelSourceMapper() + fileprivate var diagram: DVGAudioWaveformDiagram! + fileprivate var diagramViewModel = DVGAudioWaveformDiagramModel() + fileprivate var samplesReader: AudioSamplesReader! + fileprivate var waveformDataSource = ScalableChannelsContainer() + fileprivate var channelSourceMapper = ChannelSourceMapper() //MARK: - Public vars weak var movementDelegate: DVGDiagramMovementsDelegate? @@ -123,7 +123,7 @@ class DVGWaveformController: NSObject { var scale: CGFloat = 1.0 @objc var playbackRelativePosition: NSNumber? { - get { return self._playbackRelativePosition } + get { return self._playbackRelativePosition as NSNumber? } set { self._playbackRelativePosition = newValue == nil ? nil : CGFloat(newValue!) } } @@ -132,17 +132,17 @@ class DVGWaveformController: NSObject { set { self.diagram.playbackRelativePosition = newValue } } - var progress: NSProgress { + var progress: Progress { return self.samplesReader.progress } } ////MARK: - DiagramViewModelDelegate extension DVGWaveformController: DVGDiagramMovementsDelegate { - func diagramDidSelect(dataRange: DataRange) { + func diagramDidSelect(_ dataRange: DataRange) { self.movementDelegate?.diagramDidSelect(dataRange) } - func diagramMoved(scale scale: Double, start: Double) { + func diagramMoved(scale: Double, start: Double) { self.waveformDataSource.reset(DataRange(location: start, length: 1/scale)) self.movementDelegate?.diagramMoved(scale: scale, start: start) } diff --git a/Source/Data Source/AudioSamplesReader.swift b/Source/Data Source/AudioSamplesReader.swift index 4240dcc..1d1b257 100644 --- a/Source/Data Source/AudioSamplesReader.swift +++ b/Source/Data Source/AudioSamplesReader.swift @@ -29,9 +29,9 @@ class AudioSamplesReader: NSObject { var nativeAudioFormat: AudioFormat? var samplesReadAudioFormat = Constants.DefaultAudioFormat - var progress = NSProgress() + var progress = Progress() - func readAudioFormat(completionBlock: (AudioFormat?, SamplesReaderError?) -> ()) { + func readAudioFormat(completionBlock: @escaping (AudioFormat?, SamplesReaderError?) -> ()) { dispatch_asynch_on_global_processing_queue { do { self.nativeAudioFormat = try self.readAudioFormat() @@ -50,17 +50,24 @@ class AudioSamplesReader: NSObject { func readAudioFormat() throws -> AudioFormat { - let formatDescription = try soundFormatDescription() + guard let formatDescription = try? soundFormatDescription() else { + throw SamplesReaderError.UnknownError(nil) + } +#if DEBUG print("DEBUG Audio format description => \(formatDescription)") - let asbd = CMAudioFormatDescriptionGetStreamBasicDescription(formatDescription).memory +#endif + guard let asbd = CMAudioFormatDescriptionGetStreamBasicDescription(formatDescription)?.pointee + else { + throw SamplesReaderError.UnknownError(nil) + } let format = AudioFormat(samplesRate: Int(asbd.mSampleRate), bitsDepth: Int(asbd.mBitsPerChannel), numberOfChannels: Int(asbd.mChannelsPerFrame)) nativeAudioFormat = format return format } func assetAudioTrack() throws -> AVAssetTrack { - guard let sound = asset.tracksWithMediaType(AVMediaTypeAudio).first else { + guard let sound = asset.tracks(withMediaType: AVMediaTypeAudio).first else { throw SamplesReaderError.NoSound } return sound @@ -73,24 +80,24 @@ class AudioSamplesReader: NSObject { return formatDescription as! CMAudioFormatDescription } - private func audioReadingSettingsForFormat(audioFormat: AudioFormat) -> [String: AnyObject] { + private func audioReadingSettings(forFormat audioFormat: AudioFormat) -> [String: AnyObject] { return [ - AVFormatIDKey : NSNumber(unsignedInt: kAudioFormatLinearPCM), - AVSampleRateKey : audioFormat.samplesRate, - AVNumberOfChannelsKey : audioFormat.numberOfChannels, - AVLinearPCMBitDepthKey : audioFormat.bitsDepth > 0 ? audioFormat.bitsDepth : 16, - AVLinearPCMIsBigEndianKey : false, - AVLinearPCMIsFloatKey : false, - AVLinearPCMIsNonInterleaved : false + AVFormatIDKey : NSNumber(value: kAudioFormatLinearPCM), + AVSampleRateKey : audioFormat.samplesRate as AnyObject, + AVNumberOfChannelsKey : audioFormat.numberOfChannels as AnyObject, + AVLinearPCMBitDepthKey : (audioFormat.bitsDepth > 0 ? audioFormat.bitsDepth : 16) as AnyObject, + AVLinearPCMIsBigEndianKey : false as AnyObject, + AVLinearPCMIsFloatKey : false as AnyObject, + AVLinearPCMIsNonInterleaved : false as AnyObject ] } - func readSamples(audioFormat: AudioFormat? = nil, completion: (ErrorType?) -> ()) { + func readSamples(_ audioFormat: AudioFormat? = nil, completion: @escaping (Error?) -> ()) { dispatch_asynch_on_global_processing_queue({ try self.readSamples(audioFormat) }, onCatch: completion) } - func readSamples(audioFormat: AudioFormat? = nil) throws { + func readSamples(_ audioFormat: AudioFormat? = nil) throws { if let format = audioFormat { samplesReadAudioFormat = format } @@ -109,11 +116,11 @@ class AudioSamplesReader: NSObject { throw SamplesReaderError.UnknownError(error) } - let settings = audioReadingSettingsForFormat(samplesReadAudioFormat) + let settings = audioReadingSettings(forFormat: samplesReadAudioFormat) let readerOutput = AVAssetReaderTrackOutput(track: sound, outputSettings: settings) - assetReader.addOutput(readerOutput) + assetReader.add(readerOutput) assetReader.timeRange = CMTimeRange(start: kCMTimeZero, duration: asset.duration) if samplesHandler == nil { @@ -139,13 +146,13 @@ final class SamplesReadingRoutine { let audioFormat: AudioFormat weak var samplesHandler: AudioSamplesHandler? - let progress: NSProgress + let progress: Progress lazy var estimatedSamplesCount: Int = { return Int(self.assetReader.asset.duration.seconds * Double(self.audioFormat.samplesRate)) }() - init(assetReader: AVAssetReader, readerOutput: AVAssetReaderOutput, audioFormat: AudioFormat, samplesHandler: AudioSamplesHandler?, progress: NSProgress) { + init(assetReader: AVAssetReader, readerOutput: AVAssetReaderOutput, audioFormat: AudioFormat, samplesHandler: AudioSamplesHandler?, progress: Progress) { self.assetReader = assetReader self.readerOutput = readerOutput self.audioFormat = audioFormat @@ -155,12 +162,12 @@ final class SamplesReadingRoutine { } var isReading: Bool { - return assetReader.status == .Reading + return assetReader.status == .reading } func startReading() throws { if !assetReader.startReading() { - throw SamplesReaderError.CantReadSamples(assetReader.error) + throw SamplesReaderError.CantReadSamples(assetReader.error as NSError?) } } @@ -182,7 +189,7 @@ final class SamplesReadingRoutine { } } try checkStatusOfAssetReaderOnComplete() - self.samplesHandler?.didStopReadSamples(Int(self.progress.completedUnitCount)) + self.samplesHandler?.didStopReadSamples(count: Int(self.progress.completedUnitCount)) } func readNextSamples() throws { @@ -198,26 +205,29 @@ final class SamplesReadingRoutine { let length = CMBlockBufferGetDataLength(buffer) // Append new data - let tempBytes = UnsafeMutablePointer.alloc(length) - var returnedPointer: UnsafeMutablePointer = nil + let tempBytes = UnsafeMutableRawPointer.allocate(bytes: length, alignedTo: 0) + var returnedPointer: UnsafeMutablePointer? if CMBlockBufferAccessDataBytes(buffer, 0, length, tempBytes, &returnedPointer) != kCMBlockBufferNoErr { throw NoEnoughData() } - tempBytes.destroy(length) - tempBytes.dealloc(length) + tempBytes.deallocate(bytes: length, alignedTo: 0) + + guard (returnedPointer != nil) else { + throw SamplesReaderError.UnknownError(nil) + } - let samplesContainer = AudioSamplesContainer(buffer: returnedPointer, length: length, numberOfChannels: audioFormat.numberOfChannels) + let samplesContainer = AudioSamplesContainer(buffer: returnedPointer!, length: length, numberOfChannels: audioFormat.numberOfChannels) samplesHandler?.handleSamples(samplesContainer) progress.completedUnitCount += samplesContainer.samplesCount } func checkStatusOfAssetReaderOnComplete() throws { switch assetReader.status { - case .Unknown, .Failed, .Reading: - throw SamplesReaderError.UnknownError(assetReader.error) - case .Cancelled, .Completed: + case .unknown, .failed, .reading: + throw SamplesReaderError.UnknownError(assetReader.error as NSError?) + case .cancelled, .completed: return } } diff --git a/Source/Data Source/ScalableChannelsContainer.swift b/Source/Data Source/ScalableChannelsContainer.swift index ba82947..535cdab 100644 --- a/Source/Data Source/ScalableChannelsContainer.swift +++ b/Source/Data Source/ScalableChannelsContainer.swift @@ -20,7 +20,7 @@ class ScalableChannelsContainer: NSObject, ChannelSource, AudioSamplesHandler { //MARK: - //MARK: - Inner configuration - func configure(neededSamplesCount neededSamplesCount: Int, estimatedSampleCount: Int) { + func configure(neededSamplesCount: Int, estimatedSampleCount: Int) { print("estimatedSampleCount ", estimatedSampleCount) @@ -61,7 +61,7 @@ class ScalableChannelsContainer: NSObject, ChannelSource, AudioSamplesHandler { } - func reset(dataRange: DataRange) { + func reset(_ dataRange: DataRange) { assert(self.channels.count > 0, "you should configure channels first. see method above") let scale = 1.0 / dataRange.length @@ -73,7 +73,7 @@ class ScalableChannelsContainer: NSObject, ChannelSource, AudioSamplesHandler { } } - func willStartReadSamples(estimatedSampleCount estimatedSampleCount: Int) { + func willStartReadSamples(estimatedSampleCount: Int) { configure(neededSamplesCount: neededSamplesCount, estimatedSampleCount: estimatedSampleCount) } @@ -83,7 +83,7 @@ class ScalableChannelsContainer: NSObject, ChannelSource, AudioSamplesHandler { } } - func handleSamples(samplesContainer: AudioSamplesContainer) { + func handleSamples(_ samplesContainer: AudioSamplesContainer) { for channelIndex in 0.. Channel { + func channelAtIndex(_ index: Int) -> Channel { return channels[index + scaleIndex * channelsCount] } } diff --git a/Source/Utility/AudioSamplesContainer.swift b/Source/Utility/AudioSamplesContainer.swift index e22a241..9149e2e 100644 --- a/Source/Utility/AudioSamplesContainer.swift +++ b/Source/Utility/AudioSamplesContainer.swift @@ -14,14 +14,16 @@ struct AudioSamplesContainer { let numberOfChannels: Int init(buffer: UnsafePointer, length: Int, numberOfChannels: Int) { - self.buffer = UnsafePointer(buffer) - self.samplesCount = length * sizeof(T)/sizeof(Int16) / numberOfChannels + + let data = NSData(bytes: buffer, length: length) + self.buffer = data.bytes.assumingMemoryBound(to: Int16.self) + self.samplesCount = length * MemoryLayout.size/MemoryLayout.size / numberOfChannels self.numberOfChannels = numberOfChannels } - func sample(channelIndex channelIndex: Int, sampleIndex: Int) -> Int16 { + func sample(channelIndex: Int, sampleIndex: Int) -> Int16 { assert(channelIndex < numberOfChannels) assert(sampleIndex < samplesCount) return buffer[numberOfChannels * sampleIndex + channelIndex] } -} \ No newline at end of file +} diff --git a/Source/Utility/Buffer.swift b/Source/Utility/Buffer.swift index 8047111..d9e9c34 100644 --- a/Source/Utility/Buffer.swift +++ b/Source/Utility/Buffer.swift @@ -14,70 +14,82 @@ class Buffer { var maxValue = -Double.infinity var minValue = Double.infinity var count = 0 - var buffer: UnsafeMutablePointer = nil - var _buffer: UnsafeMutablePointer = nil - private var space = 0 + var buffer: UnsafeMutableRawPointer? + var _buffer: UnsafeMutablePointer? + fileprivate var space = 0 - func appendValue(value: Double) { + func append(value: Double) { if maxValue < value { maxValue = value } if minValue > value { minValue = value } if space == count { let newSpace = max(space * 2, 16) - self.moveSpaceTo(newSpace) - _buffer = UnsafeMutablePointer(buffer) + self.moveSpace(to: newSpace) + _buffer = UnsafeMutablePointer(buffer?.assumingMemoryBound(to: DefaultNumberType.self)) } - (UnsafeMutablePointer(buffer) + count).initialize(value) + (UnsafeMutablePointer((buffer?.assumingMemoryBound(to: DefaultNumberType.self))!) + count).initialize(to: value) count += 1 } - private - func moveSpaceTo(newSpace: Int) { - let newPtr = UnsafeMutablePointer.alloc(newSpace) + fileprivate + func moveSpace(to newSpace: Int) { + let newPtr = UnsafeMutablePointer.allocate(capacity: newSpace) - newPtr.moveInitializeFrom(UnsafeMutablePointer(buffer), count: count) + newPtr.moveInitialize(from: UnsafeMutablePointer((buffer?.assumingMemoryBound(to: DefaultNumberType.self))!), count: count) - buffer.dealloc(count) + buffer?.deallocate(bytes: count, alignedTo: 0) - buffer = UnsafeMutablePointer(newPtr) + buffer = UnsafeMutableRawPointer(newPtr) space = newSpace } - func valueAtIndex(index: Int) -> Double { - return _buffer[index] + + subscript(index: Int) -> Double { + return _buffer?[index] ?? Double.infinity + } + + func value(atIndex index: Int) -> Double { + return _buffer?[index] ?? Double.infinity } } final class GenericBuffer: Buffer { - var __buffer: UnsafeMutablePointer = nil + var __buffer: UnsafeMutablePointer? - override final func appendValue(value: Double) { + override final func append(value: Double) { + + guard (__buffer != nil) else {return} if maxValue < value { maxValue = value } if minValue > value { minValue = value } if space == count { let newSpace = max(space * 2, 16) - self.moveSpaceTo(newSpace) + self.moveSpace(to: newSpace) } - (__buffer + count).initialize(T(value)) + (__buffer! + count).initialize(to: T(value)) count += 1 } - override final func moveSpaceTo(newSpace: Int) { - let newPtr = UnsafeMutablePointer.alloc(newSpace) + override final func moveSpace(to newSpace: Int) { + + guard (__buffer != nil) else {return} - newPtr.moveInitializeFrom(__buffer, count: count) + let newPtr = UnsafeMutablePointer.allocate(capacity: newSpace) - __buffer.dealloc(count) + newPtr.moveInitialize(from: __buffer!, count: count) + + __buffer!.deallocate(capacity: count) __buffer = newPtr space = newSpace } - override final func valueAtIndex(index: Int) -> Double { - return __buffer[index].double + + override subscript(index: Int) -> Double { + return __buffer?[index].double ?? Double.infinity } + deinit { - __buffer.destroy(space) - __buffer.dealloc(space) + __buffer?.deinitialize(count: space) + __buffer?.deallocate(capacity: space) } -} \ No newline at end of file +} diff --git a/Source/Utility/Channel.swift b/Source/Utility/Channel.swift index ed0dbb5..b2771a6 100644 --- a/Source/Utility/Channel.swift +++ b/Source/Utility/Channel.swift @@ -22,7 +22,7 @@ class Channel { public var blockSize = 1 public var count: Int { return buffer.count } public var totalCount: Int = 0 - lazy public var identifier: String = { return "\(self.logicProvider.dynamicType)" }() + lazy public var identifier: String = { return "\(type(of: self.logicProvider))" }() private var currentBlockSize = 0 public var maxValue: Double { return buffer.maxValue } @@ -31,11 +31,11 @@ class Channel { public subscript(index: Int) -> Double { get { - return buffer.valueAtIndex(index) + return buffer[index] } } - public func handleValue(value: U) { + public func handle(value: U) { if currentBlockSize == blockSize { self.clear() currentBlockSize = 0 @@ -44,8 +44,8 @@ class Channel { self.logicProvider.handleValue(value.double) } - func appendValueToBuffer(value: Double) { - buffer.appendValue(value) + func appendValueToBuffer(_ value: Double) { + buffer.append(value: value) onUpdate() } @@ -60,4 +60,4 @@ class Channel { //TODO: Clear odd space self.clear() } -} \ No newline at end of file +} diff --git a/Source/Utility/DiagramGeometry.swift b/Source/Utility/DiagramGeometry.swift index e9a77f0..f890098 100644 --- a/Source/Utility/DiagramGeometry.swift +++ b/Source/Utility/DiagramGeometry.swift @@ -15,32 +15,32 @@ struct DiagramGeometry { } extension Double { - func convertToGeometry(geometry: DiagramGeometry) -> Double { + func convertToGeometry(_ geometry: DiagramGeometry) -> Double { return (self - geometry.start) * geometry.scale } - func convertFromGeometry(geometry: DiagramGeometry) -> Double { + func convertFromGeometry(_ geometry: DiagramGeometry) -> Double { return self/geometry.scale + geometry.start } } extension CGFloat { - func convertToGeometry(geometry: DiagramGeometry) -> CGFloat { + func convertToGeometry(_ geometry: DiagramGeometry) -> CGFloat { return CGFloat((Double(self) - geometry.start) * geometry.scale) } - func convertFromGeometry(geometry: DiagramGeometry) -> CGFloat { + func convertFromGeometry(_ geometry: DiagramGeometry) -> CGFloat { return CGFloat(Double(self)/geometry.scale + geometry.start) } } extension DataRange { - func convertToGeometry(geometry: DiagramGeometry) -> DataRange { + func convertToGeometry(_ geometry: DiagramGeometry) -> DataRange { let location = self.location.convertToGeometry(geometry) let length = self.length * geometry.scale return DataRange(location: location, length: length) } - func convertFromGeometry(geometry: DiagramGeometry) -> DataRange { + func convertFromGeometry(_ geometry: DiagramGeometry) -> DataRange { let location = self.location.convertFromGeometry(geometry) let length = self.length / geometry.scale return DataRange(location: location, length: length) } -} \ No newline at end of file +} diff --git a/Source/Utility/Dispatch.swift b/Source/Utility/Dispatch.swift index 7da0526..4b5132e 100644 --- a/Source/Utility/Dispatch.swift +++ b/Source/Utility/Dispatch.swift @@ -8,17 +8,20 @@ import Foundation -let processingQueue = dispatch_queue_create("ru.denivip.waveform.processing", DISPATCH_QUEUE_SERIAL) +let processingQueue = DispatchQueue(label: "ru.denivip.waveform.processing")// dispatch_queue_create("ru.denivip.waveform.processing", DISPATCH_QUEUE_SERIAL) -public func dispatch_asynch_on_global_processing_queue(block: dispatch_block_t) { - if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(processingQueue)) { - autoreleasepool(block) +public func dispatch_asynch_on_global_processing_queue(block: @escaping ()->() ) { + + + + if processingQueue.label == String(cString:__dispatch_queue_get_label(nil),encoding: .utf8) { + autoreleasepool(invoking: block) } else { - dispatch_async(processingQueue, block); + processingQueue.async(execute: block) } } -public func dispatch_asynch_on_global_processing_queue(body: () throws -> (), onCatch: (ErrorType?) -> ()) { +public func dispatch_asynch_on_global_processing_queue(_ body: @escaping () throws -> (), onCatch: @escaping (Error?) -> ()) { dispatch_asynch_on_global_processing_queue { do { try body() @@ -28,4 +31,4 @@ public func dispatch_asynch_on_global_processing_queue(body: () throws -> (), on onCatch(error) } } -} \ No newline at end of file +} diff --git a/Source/Utility/Error.swift b/Source/Utility/Error.swift index 596d6a2..b2256a1 100644 --- a/Source/Utility/Error.swift +++ b/Source/Utility/Error.swift @@ -8,7 +8,7 @@ import Foundation -enum SamplesReaderError: ErrorType { +enum SamplesReaderError: Error { case NoSound case InvalidAudioFormat case CantReadSamples(NSError?) @@ -16,5 +16,5 @@ enum SamplesReaderError: ErrorType { case SampleReaderNotReady } -struct NoMoreSampleBuffersAvailable: ErrorType {} -struct NoEnoughData: ErrorType {} \ No newline at end of file +struct NoMoreSampleBuffersAvailable: Error {} +struct NoEnoughData: Error {} diff --git a/Source/Utility/LogicProvider.swift b/Source/Utility/LogicProvider.swift index 7093155..36df3e6 100644 --- a/Source/Utility/LogicProvider.swift +++ b/Source/Utility/LogicProvider.swift @@ -11,7 +11,7 @@ import Foundation public class LogicProvider { weak internal var channel: Channel? - public func handleValue(value: Double) {} + public func handleValue(_ value: Double) {} public func clear() {} } @@ -21,7 +21,7 @@ class MaxValueLogicProvider: LogicProvider { private var max: Double? public override init(){} - public override func handleValue(value: Double) { + public override func handleValue(_ value: Double) { if max == nil { max = value } else if value > max! { @@ -42,7 +42,7 @@ class AverageValueLogicProvider: LogicProvider { var count = 0 public override init(){} - public override func handleValue(value: Double) { + public override func handleValue(_ value: Double) { summ = summ + value count += 1 } @@ -61,7 +61,7 @@ class AudioMaxValueLogicProvider: LogicProvider { private var max = Double(Int16.min)//-40.0 public override init(){} - public override func handleValue(value: Double) { + public override func handleValue(_ value: Double) { let value = abs(value) if value > max { max = value @@ -81,7 +81,7 @@ class AudioAverageValueLogicProvider: LogicProvider { var count = 0 public override init(){} - public override func handleValue(value: Double) { + public override func handleValue(_ value: Double) { summ = summ + abs(value) count += 1 } diff --git a/Source/Utility/Protocols.swift b/Source/Utility/Protocols.swift index 09319b7..d168b13 100644 --- a/Source/Utility/Protocols.swift +++ b/Source/Utility/Protocols.swift @@ -14,29 +14,29 @@ protocol PlotDataSource: class { var pointsCount: Int { get } var needsRedraw: Bool { get set } func updateGeometry() - func pointAtIndex(index: Int) -> CGPoint + func pointAtIndex(_ index: Int) -> CGPoint } protocol DiagramDataSource: class { var geometry: DiagramGeometry { get } var onPlotUpdate: () -> () { get set } var plotDataSourcesCount: Int { get } - func plotDataSourceAtIndex(index: Int) -> PlotDataSource + func plotDataSourceAtIndex(_ index: Int) -> PlotDataSource } protocol DiagramDelegate: class { - func zoomAt(zoomAreaCenter: CGFloat, relativeScale: CGFloat) - func moveByDistance(relativeDeltaX: CGFloat) + func zoomAt(_ zoomAreaCenter: CGFloat, relativeScale: CGFloat) + func moveByDistance(_ relativeDeltaX: CGFloat) } protocol DVGDiagramDelegate: class, DiagramDelegate { - func diagramDidSelect(dataRange: DataRange) + func diagramDidSelect(_ dataRange: DataRange) } protocol ChannelSource: class { var channelsCount: Int { get } var onChannelsChanged: () -> () { get set } - func channelAtIndex(index: Int) -> Channel + func channelAtIndex(_ index: Int) -> Channel } protocol AbstractChannel: class, Identifiable { @@ -47,13 +47,13 @@ protocol AbstractChannel: class, Identifiable { var minValue: Double { get } subscript(index: Int) -> Double { get } - func handleValue(value: U) + func handleValue(_ value: U) } protocol AudioSamplesHandler: class { - func willStartReadSamples(estimatedSampleCount estimatedSampleCount: Int) + func willStartReadSamples(estimatedSampleCount: Int) func didStopReadSamples(count: Int) - func handleSamples(samplesContainer: AudioSamplesContainer) + func handleSamples(_ samplesContainer: AudioSamplesContainer) } extension AudioSamplesHandler { @@ -64,4 +64,4 @@ extension AudioSamplesHandler { protocol Identifiable { var identifier: String { get } -} \ No newline at end of file +} diff --git a/Source/Utility/UIKit+extensions.swift b/Source/Utility/UIKit+extensions.swift index baadafb..d5e820e 100644 --- a/Source/Utility/UIKit+extensions.swift +++ b/Source/Utility/UIKit+extensions.swift @@ -12,9 +12,9 @@ extension UIView { func attachBoundsOfSuperview(){ assert(self.superview != nil, "There are no superview") let views = ["view": self] - let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("|[view]|", options: [], metrics: nil, views: views) + let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "|[view]|", options: [], metrics: nil, views: views) self.superview!.addConstraints(horizontalConstraints) - let verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|[view]|", options: [], metrics: nil, views: views) + let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|", options: [], metrics: nil, views: views) self.superview!.addConstraints(verticalConstraints) } -} \ No newline at end of file +} diff --git a/Source/View Model/ChannelSourceMapper.swift b/Source/View Model/ChannelSourceMapper.swift index ba509b6..0e2fa43 100644 --- a/Source/View Model/ChannelSourceMapper.swift +++ b/Source/View Model/ChannelSourceMapper.swift @@ -11,7 +11,7 @@ import Foundation class ChannelSourceMapper: ChannelSource { var channelSources: [ChannelSource] = [] - func addChannelSource(channelSource: ChannelSource) { + func addChannelSource(_ channelSource: ChannelSource) { channelSources.append(channelSource) channelSource.onChannelsChanged = { [weak self] in self?.onChannelsChanged() } } @@ -21,7 +21,7 @@ class ChannelSourceMapper: ChannelSource { } var onChannelsChanged: () -> () = {_ in} - func channelAtIndex(index: Int) -> Channel { + func channelAtIndex(_ index: Int) -> Channel { var tmpIndex = index for channelSource in channelSources { if tmpIndex < channelSource.channelsCount { @@ -31,4 +31,4 @@ class ChannelSourceMapper: ChannelSource { } fatalError() } -} \ No newline at end of file +} diff --git a/Source/View Model/DiagramModel.swift b/Source/View Model/DiagramModel.swift index ed023cf..c8dc3b9 100644 --- a/Source/View Model/DiagramModel.swift +++ b/Source/View Model/DiagramModel.swift @@ -21,13 +21,13 @@ class DiagramModel: NSObject, DiagramDataSource { } } - private var viewModels = [PlotModel]() + fileprivate var viewModels = [PlotModel]() var geometry = DiagramGeometry() var onPlotUpdate: () -> () = {} var onGeometryUpdate: () -> () = {} var plotDataSourcesCount: Int { return self.viewModels.count } - func plotDataSourceAtIndex(index: Int) -> PlotDataSource { + func plotDataSourceAtIndex(_ index: Int) -> PlotDataSource { return self.viewModels[index] } @@ -46,7 +46,7 @@ class DiagramModel: NSObject, DiagramDataSource { onPlotUpdate() } - func adjustViewModelsCountWithCount(count: Int) { + func adjustViewModelsCountWithCount(_ count: Int) { if viewModels.count == count { return } @@ -92,29 +92,29 @@ class DiagramModel: NSObject, DiagramDataSource { } extension DiagramModel: DiagramDelegate { - func zoom(start start: CGFloat, scale: CGFloat) { + func zoom(start: CGFloat, scale: CGFloat) { self.geometry = DiagramGeometry(start: Double(start), scale: Double(scale)) for viewModel in self.viewModels { viewModel.updateGeometry() } } - func zoomAt(zoomAreaCenter: CGFloat, relativeScale: CGFloat) { + func zoomAt(_ zoomAreaCenter: CGFloat, relativeScale: CGFloat) { let newScale = max(1.0, relativeScale * CGFloat(self.geometry.scale)) var start = CGFloat(self.geometry.start) + zoomAreaCenter * (1/CGFloat(self.geometry.scale) - 1/newScale) start = max(0, min(start, 1 - 1/newScale)) self.zoom(start: start, scale: newScale) } - func moveToPosition(start: CGFloat) { + func moveToPosition(_ start: CGFloat) { self.geometry.start = max(0, min(Double(start), 1 - 1/self.geometry.scale)) for viewModel in self.viewModels { viewModel.updateGeometry() } } - func moveByDistance(relativeDeltaX: CGFloat) { + func moveByDistance(_ relativeDeltaX: CGFloat) { let relativeStart = CGFloat(self.geometry.start) - relativeDeltaX / CGFloat(self.geometry.scale) self.moveToPosition(relativeStart) } -} \ No newline at end of file +} diff --git a/Source/View Model/PlotModel.swift b/Source/View Model/PlotModel.swift index bd64c7b..c4d4acc 100644 --- a/Source/View Model/PlotModel.swift +++ b/Source/View Model/PlotModel.swift @@ -46,7 +46,7 @@ class PlotModel: NSObject, PlotDataSource { var identifier = "" var needsRedraw = false - func pointAtIndex(index: Int) -> CGPoint { + func pointAtIndex(_ index: Int) -> CGPoint { guard let channel = self.channel else { return .zero } diff --git a/Source/View/Diagram.swift b/Source/View/Diagram.swift index 09291b6..74969b7 100644 --- a/Source/View/Diagram.swift +++ b/Source/View/Diagram.swift @@ -60,7 +60,7 @@ class Diagram: UIView { self.containerView = containerView } - func adjustPlotsNumberWithCount(count: Int) { + func adjustPlotsNumberWithCount(_ count: Int) { if plots.count == count { return } @@ -77,7 +77,7 @@ class Diagram: UIView { for index in count.. Plot { + func addPlotWithDataSource(_ dataSource: PlotDataSource) -> Plot { let plot = Plot(frame: self.bounds) plot.dataSource = dataSource @@ -102,7 +102,7 @@ extension Diagram { return plot } - func plotWithIdentifier(identifier: String) -> Plot? { + func plotWithIdentifier(_ identifier: String) -> Plot? { for plot in self.plots { if plot.identifier == identifier { return plot @@ -113,7 +113,7 @@ extension Diagram { func redraw() { for plot in self.plots { - if let dataSource = plot.dataSource where dataSource.needsRedraw { + if let dataSource = plot.dataSource , dataSource.needsRedraw { plot.redraw() dataSource.needsRedraw = false } @@ -126,7 +126,7 @@ extension Diagram { self.displayLink = nil } let displayLink = CADisplayLink.init(target: self, selector: #selector(Diagram.redraw)) - displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes) + displayLink.add(to: RunLoop.current, forMode: .commonModes) self.displayLink = displayLink } @@ -134,4 +134,4 @@ extension Diagram { self.displayLink?.invalidate() self.displayLink = nil } -} \ No newline at end of file +} diff --git a/Source/View/PlaybackPositionView.swift b/Source/View/PlaybackPositionView.swift index e799f1b..9214840 100644 --- a/Source/View/PlaybackPositionView.swift +++ b/Source/View/PlaybackPositionView.swift @@ -12,16 +12,16 @@ class PlaybackPositionView: UIView { init() { super.init(frame: .zero) - self.opaque = false + self.isOpaque = false } - + required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - self.opaque = false + self.isOpaque = false } - - override func drawRect(rect: CGRect) { - super.drawRect(rect) + + override func draw(_ rect: CGRect) { + super.draw(rect) guard let relativePosition = self.position else { return } @@ -36,17 +36,18 @@ class PlaybackPositionView: UIView { fatalError("No context") } - CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor) - CGContextSetLineWidth(context, lineWidth) + context.setStrokeColor(self.lineColor.cgColor) + context.setLineWidth(lineWidth) + + let cursor = CGMutablePath() - let cursor = CGPathCreateMutable() - CGPathMoveToPoint(cursor, nil, position, 0) - CGPathAddLineToPoint(cursor, nil, position, self.bounds.height) - CGContextAddPath(context, cursor) + cursor.move(to: CGPoint(x:position,y:0)) + cursor.addLine(to: CGPoint(x:position,y:self.bounds.height)) + context.addPath(cursor) - CGContextStrokePath(context) + context.strokePath() } @@ -56,6 +57,6 @@ class PlaybackPositionView: UIView { var position: CGFloat? { didSet { self.setNeedsDisplay() } } - var lineColor = UIColor.whiteColor() + var lineColor = UIColor.white var lineWidth: CGFloat = 2.0 } diff --git a/Source/View/Plot.swift b/Source/View/Plot.swift index 90e20fa..b6d22c6 100644 --- a/Source/View/Plot.swift +++ b/Source/View/Plot.swift @@ -16,7 +16,7 @@ class Plot: UIView { } } - var lineColor: UIColor = .blackColor() { + var lineColor: UIColor = .black{ didSet{ // self.pathLayer.strokeColor = lineColor.CGColor } @@ -28,23 +28,23 @@ class Plot: UIView { required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - self.opaque = false + self.isOpaque = false } convenience init(){ - self.init(frame: CGRectZero) - self.opaque = false + self.init(frame: .zero) + self.isOpaque = false } override init(frame: CGRect) { super.init(frame: frame) - self.opaque = false + self.isOpaque = false } func setupPathLayer() { self.pathLayer = CAShapeLayer() - self.pathLayer.strokeColor = UIColor.blackColor().CGColor + self.pathLayer.strokeColor = UIColor.black.cgColor self.pathLayer.lineWidth = 1.0 self.layer.addSublayer(self.pathLayer) @@ -60,33 +60,33 @@ class Plot: UIView { self.setNeedsDisplay() } - override func drawRect(rect: CGRect) { + override func draw(_ rect: CGRect) { guard let context = UIGraphicsGetCurrentContext() else { return } - CGContextSetLineWidth(context, 1)///UIScreen.mainScreen().scale) - CGContextAddPath(context, self.newPathPart()) - CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor) - CGContextSetInterpolationQuality(context, .None); - CGContextSetAllowsAntialiasing(context, false); - CGContextSetShouldAntialias(context, false); - CGContextStrokePath(context) + context.setLineWidth(1)///UIScreen.mainScreen().scale) + context.addPath(self.newPathPart()) + context.setStrokeColor(self.lineColor.cgColor) + context.interpolationQuality = .none + context.setAllowsAntialiasing(false) + context.setShouldAntialias(false) + context.strokePath() } - private func newPathPart() -> CGPathRef { + private func newPathPart() -> CGPath { let lineWidth: CGFloat = 1 guard let dataSource = self.dataSource else { - return CGPathCreateMutable() + return CGMutablePath() } let currentCount = dataSource.pointsCount let sourceBounds = dataSource.dataSourceFrame.size - let mPath = CGPathCreateMutable() - CGPathMoveToPoint(mPath, nil, 0, self.bounds.midY - lineWidth/2) + let mPath = CGMutablePath() + mPath.move(to: CGPoint(x: 0,y: self.bounds.midY - lineWidth/2)) let wProportion = self.bounds.size.width / sourceBounds.width let hPropostion = self.bounds.size.height / sourceBounds.height @@ -97,14 +97,15 @@ class Plot: UIView { x: point.x * wProportion, y: point.y * hPropostion / 2.0) - CGPathAddLineToPoint(mPath, nil, adjustedPoint.x, self.bounds.midY) - CGPathAddLineToPoint(mPath, nil, adjustedPoint.x, self.bounds.midY - adjustedPoint.y) - CGPathAddLineToPoint(mPath, nil, adjustedPoint.x, self.bounds.midY + adjustedPoint.y) - CGPathAddLineToPoint(mPath, nil, adjustedPoint.x, self.bounds.midY) + mPath.addLine(to: CGPoint(x: adjustedPoint.x, y: self.bounds.midY)) + mPath.addLine(to: CGPoint(x: adjustedPoint.x, y: self.bounds.midY - adjustedPoint.y)) + mPath.addLine(to: CGPoint(x: adjustedPoint.x, y: self.bounds.midY + adjustedPoint.y)) + mPath.addLine(to: CGPoint(x: adjustedPoint.x, y: self.bounds.midY)) + } - CGPathAddLineToPoint(mPath, nil, 0.0, self.bounds.midY) - CGPathCloseSubpath(mPath) + mPath.addLine(to: CGPoint(x: 0.0,y: self.bounds.midY)) + mPath.closeSubpath() return mPath } } diff --git a/Source/View/SelectionView.swift b/Source/View/SelectionView.swift index 77f1b3c..9902064 100644 --- a/Source/View/SelectionView.swift +++ b/Source/View/SelectionView.swift @@ -25,15 +25,15 @@ class SelectionView: UIView { func setup() { self.setupSelectionLayer() - self.backgroundColor = .clearColor() + self.backgroundColor = .clear } func setupSelectionLayer() { let layer = CALayer() - layer.borderColor = UIColor.grayColor().CGColor + layer.borderColor = UIColor.gray.cgColor layer.cornerRadius = 5.0 layer.borderWidth = 2.0 - layer.backgroundColor = UIColor.clearColor().CGColor + layer.backgroundColor = UIColor.clear.cgColor self.layer.addSublayer(layer) self.selectionLayer = layer } @@ -47,12 +47,12 @@ class SelectionView: UIView { didSet{ self.layoutSelection(selection) } } - func layoutSelection(dataRange: DataRange?) { + func layoutSelection(_ dataRange: DataRange?) { guard let dataRange = dataRange else { - self.selectionLayer.borderColor = UIColor.clearColor().CGColor + self.selectionLayer.borderColor = UIColor.clear.cgColor return } - self.selectionLayer.borderColor = UIColor.grayColor().CGColor + self.selectionLayer.borderColor = UIColor.gray.cgColor let startLocation = self.bounds.width * CGFloat(dataRange.location) let selectionWidth = self.bounds.width * CGFloat(dataRange.length) From 7a0019173682e7c455a7dbbb7dbab74aba3151fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Mon, 10 Oct 2016 18:02:14 +0300 Subject: [PATCH 03/31] Swift3. Migration completed. --- Source/Utility/Buffer.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Utility/Buffer.swift b/Source/Utility/Buffer.swift index d9e9c34..b6f9757 100644 --- a/Source/Utility/Buffer.swift +++ b/Source/Utility/Buffer.swift @@ -57,7 +57,6 @@ class GenericBuffer: Buffer { override final func append(value: Double) { - guard (__buffer != nil) else {return} if maxValue < value { maxValue = value } if minValue > value { minValue = value } @@ -66,21 +65,22 @@ class GenericBuffer: Buffer { let newSpace = max(space * 2, 16) self.moveSpace(to: newSpace) } + guard (__buffer != nil) else {return} (__buffer! + count).initialize(to: T(value)) count += 1 } override final func moveSpace(to newSpace: Int) { - guard (__buffer != nil) else {return} - let newPtr = UnsafeMutablePointer.allocate(capacity: newSpace) - newPtr.moveInitialize(from: __buffer!, count: count) - - __buffer!.deallocate(capacity: count) - - __buffer = newPtr + if (__buffer == nil){ + __buffer = newPtr + } else { + newPtr.moveInitialize(from: __buffer!, count: count) + __buffer!.deallocate(capacity: count) + __buffer = newPtr + } space = newSpace } From bc99b0aab586642f6cb8a74fc8b035614bea6c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Mon, 10 Oct 2016 18:15:55 +0300 Subject: [PATCH 04/31] Rip off pointer conversion through nsdata. Speed up waveform rendering --- Source/Utility/AudioSamplesContainer.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/Utility/AudioSamplesContainer.swift b/Source/Utility/AudioSamplesContainer.swift index 9149e2e..1b736ba 100644 --- a/Source/Utility/AudioSamplesContainer.swift +++ b/Source/Utility/AudioSamplesContainer.swift @@ -14,9 +14,8 @@ struct AudioSamplesContainer { let numberOfChannels: Int init(buffer: UnsafePointer, length: Int, numberOfChannels: Int) { - - let data = NSData(bytes: buffer, length: length) - self.buffer = data.bytes.assumingMemoryBound(to: Int16.self) + + self.buffer = UnsafeRawPointer(buffer).assumingMemoryBound(to: Int16.self) self.samplesCount = length * MemoryLayout.size/MemoryLayout.size / numberOfChannels self.numberOfChannels = numberOfChannels } From ad61c84fa2b3c3b3bc183e25e39d13d2f8122596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Tue, 1 Nov 2016 17:31:18 +0300 Subject: [PATCH 05/31] Semaphore for buffer to preven concurent read/write access --- Source/Utility/Channel.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/Utility/Channel.swift b/Source/Utility/Channel.swift index 3736d3e..666f578 100644 --- a/Source/Utility/Channel.swift +++ b/Source/Utility/Channel.swift @@ -14,6 +14,7 @@ class Channel: NSObject { let logicProvider: LogicProvider let buffer: Buffer + let semaphore = DispatchSemaphore.init(value: 1) public init(logicProvider: LogicProvider, buffer: Buffer = GenericBuffer()) { self.logicProvider = logicProvider self.buffer = buffer @@ -33,7 +34,10 @@ class Channel: NSObject { public subscript(index: Int) -> Double { get { - return buffer[index] + semaphore.wait() + let result = buffer[index] + semaphore.signal() + return result } } @@ -47,7 +51,9 @@ class Channel: NSObject { } func appendValueToBuffer(_ value: Double) { + semaphore.wait() buffer.append(value: value) + semaphore.signal() onUpdate() } From a56a572605005b59bfcb8367a98b1c7e4efb90c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Fri, 11 Nov 2016 18:09:23 +0300 Subject: [PATCH 06/31] Waweform scale-pan crash fixed --- Example/Waveform.xcodeproj/project.pbxproj | 1 + Source/DVGAudioWaveformDiagramModel.swift | 1 - Source/Data Source/ScalableChannelsContainer.swift | 11 ++--------- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Example/Waveform.xcodeproj/project.pbxproj b/Example/Waveform.xcodeproj/project.pbxproj index b695fec..0c61171 100644 --- a/Example/Waveform.xcodeproj/project.pbxproj +++ b/Example/Waveform.xcodeproj/project.pbxproj @@ -437,6 +437,7 @@ PRODUCT_BUNDLE_IDENTIFIER = denivip.Waveform; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "SRC/Waveform-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; }; name = Release; diff --git a/Source/DVGAudioWaveformDiagramModel.swift b/Source/DVGAudioWaveformDiagramModel.swift index 9f06405..4944dd1 100644 --- a/Source/DVGAudioWaveformDiagramModel.swift +++ b/Source/DVGAudioWaveformDiagramModel.swift @@ -9,7 +9,6 @@ import Foundation import UIKit -@objc protocol DVGDiagramMovementsDelegate: class { func diagramDidSelect(_ dataRange: DataRange) func diagramMoved(scale: Double, start: Double) diff --git a/Source/Data Source/ScalableChannelsContainer.swift b/Source/Data Source/ScalableChannelsContainer.swift index eefca03..3daff1c 100644 --- a/Source/Data Source/ScalableChannelsContainer.swift +++ b/Source/Data Source/ScalableChannelsContainer.swift @@ -129,21 +129,14 @@ class ScalableChannelsContainer: NSObject, ChannelSource, AudioSamplesHandler { //MARK: - //MARK: - Utility -@objc public final -class DataRange: NSObject { +class DataRange { let location: Double let length: Double - init(location: Double, length: Double) { + init(location: Double = 0.0, length: Double = 1.0) { self.location = location self.length = length } - - override init() { - self.location = 0.0 - self.length = 1.0 - super.init() - } } From cc149d1ac03e2eccda7d80e076c06cf8117c9619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Mon, 14 Nov 2016 15:49:24 +0300 Subject: [PATCH 07/31] Max scale limited to one second on diagram --- Source/DVGWaveformView.swift | 1 + Source/View Model/DiagramModel.swift | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/DVGWaveformView.swift b/Source/DVGWaveformView.swift index 4ec7ccf..7744836 100644 --- a/Source/DVGWaveformView.swift +++ b/Source/DVGWaveformView.swift @@ -130,6 +130,7 @@ class DVGWaveformController: NSObject { self.samplesReader = AudioSamplesReader(asset: asset) self.configure() self.samplesReader?.samplesHandler = waveformDataSource + diagramViewModel.maxScale = asset.duration.seconds } } } diff --git a/Source/View Model/DiagramModel.swift b/Source/View Model/DiagramModel.swift index e555f9b..8de2089 100644 --- a/Source/View Model/DiagramModel.swift +++ b/Source/View Model/DiagramModel.swift @@ -13,6 +13,8 @@ import UIKit public class DiagramModel: NSObject, DiagramDataSource { + var maxScale = 100.0 + weak var channelsSource: ChannelSource? { didSet{ channelsSource?.onChannelsChanged = { @@ -103,7 +105,7 @@ extension DiagramModel: DiagramDelegate { } public func zoomAt(_ zoomAreaCenter: CGFloat, relativeScale: CGFloat) { - let newScale = max(1.0, relativeScale * CGFloat(self.geometry.scale)) + let newScale = min( max(1.0, relativeScale * CGFloat(self.geometry.scale)), CGFloat(maxScale)) var start = CGFloat(self.geometry.start) + zoomAreaCenter * (1/CGFloat(self.geometry.scale) - 1/newScale) start = max(0, min(start, 1 - 1/newScale)) self.zoom(start: start, scale: newScale) From 5e16e8803fc2696af79f47265895b90bcd188190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Mon, 14 Nov 2016 15:49:52 +0300 Subject: [PATCH 08/31] Revert "Waweform scale-pan crash fixed" This reverts commit a56a572605005b59bfcb8367a98b1c7e4efb90c2. --- Example/Waveform.xcodeproj/project.pbxproj | 1 - Source/DVGAudioWaveformDiagramModel.swift | 1 + Source/Data Source/ScalableChannelsContainer.swift | 11 +++++++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Example/Waveform.xcodeproj/project.pbxproj b/Example/Waveform.xcodeproj/project.pbxproj index 0c61171..b695fec 100644 --- a/Example/Waveform.xcodeproj/project.pbxproj +++ b/Example/Waveform.xcodeproj/project.pbxproj @@ -437,7 +437,6 @@ PRODUCT_BUNDLE_IDENTIFIER = denivip.Waveform; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "SRC/Waveform-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; }; name = Release; diff --git a/Source/DVGAudioWaveformDiagramModel.swift b/Source/DVGAudioWaveformDiagramModel.swift index 4944dd1..9f06405 100644 --- a/Source/DVGAudioWaveformDiagramModel.swift +++ b/Source/DVGAudioWaveformDiagramModel.swift @@ -9,6 +9,7 @@ import Foundation import UIKit +@objc protocol DVGDiagramMovementsDelegate: class { func diagramDidSelect(_ dataRange: DataRange) func diagramMoved(scale: Double, start: Double) diff --git a/Source/Data Source/ScalableChannelsContainer.swift b/Source/Data Source/ScalableChannelsContainer.swift index 3daff1c..eefca03 100644 --- a/Source/Data Source/ScalableChannelsContainer.swift +++ b/Source/Data Source/ScalableChannelsContainer.swift @@ -129,14 +129,21 @@ class ScalableChannelsContainer: NSObject, ChannelSource, AudioSamplesHandler { //MARK: - //MARK: - Utility +@objc public final -class DataRange { +class DataRange: NSObject { let location: Double let length: Double - init(location: Double = 0.0, length: Double = 1.0) { + init(location: Double, length: Double) { self.location = location self.length = length } + + override init() { + self.location = 0.0 + self.length = 1.0 + super.init() + } } From fea0f29f72d48169bd7b106cc69633e619c2cf6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Thu, 24 Nov 2016 16:58:21 +0300 Subject: [PATCH 09/31] Cursor image changed --- .../AppIcon.appiconset/Contents.json | 20 ++++++++++ .../Contents.json | 21 ++++++++++ .../icon-button-play-slider.pdf | Bin 0 -> 6407 bytes Example/Waveform.xcodeproj/project.pbxproj | 5 ++- Source/View/PlaybackPositionView.swift | 37 +++++++----------- 5 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/Contents.json create mode 100644 Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/icon-button-play-slider.pdf diff --git a/Example/SRC/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example/SRC/Assets.xcassets/AppIcon.appiconset/Contents.json index eeea76c..1d060ed 100644 --- a/Example/SRC/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Example/SRC/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", @@ -30,6 +40,16 @@ "size" : "60x60", "scale" : "3x" }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, { "idiom" : "ipad", "size" : "29x29", diff --git a/Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/Contents.json b/Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/Contents.json new file mode 100644 index 0000000..611046d --- /dev/null +++ b/Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "icon-button-play-slider.pdf", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/icon-button-play-slider.pdf b/Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/icon-button-play-slider.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c3285a63a968543dc421797cf81f5ca24b4661ec GIT binary patch literal 6407 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 UP?# 1 + else { + cursor.isHidden = true return } - if relativePosition < 0 || relativePosition > 1 { - return - } + cursor.isHidden = false let position = (self.bounds.width - lineWidth) * relativePosition + lineWidth/2 - guard let context = UIGraphicsGetCurrentContext() else { - fatalError("No context") - } - - context.setStrokeColor(self.lineColor.cgColor) - context.setLineWidth(lineWidth) - - - - let cursor = CGMutablePath() - - cursor.move(to: CGPoint(x:position,y:0)) - cursor.addLine(to: CGPoint(x:position,y:self.bounds.height)) - context.addPath(cursor) - - context.strokePath() + cursor.center = CGPoint(x: position, y: center.y) + self.setNeedsLayout() } /// Value from 0 to 1 /// Setting value causes setNeedsDisplay method call /// Setting nil causes removing cursor var position: CGFloat? { - didSet { self.setNeedsDisplay() } + didSet { self.positionCursor() } } var lineColor = UIColor.white var lineWidth: CGFloat = 2.0 From 5e945fad76da29ec4ba2293e95d3978a8a72159c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Thu, 24 Nov 2016 17:56:52 +0300 Subject: [PATCH 10/31] Added resources to podspec --- .../Contents.json | 21 ------------------ Example/Waveform.xcodeproj/project.pbxproj | 18 +++++++++++++-- Source/View/PlaybackPositionView.swift | 2 +- .../waweform-icon-button-play-slider.pdf | Bin Waveform.podspec | 1 + 5 files changed, 18 insertions(+), 24 deletions(-) delete mode 100644 Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/Contents.json rename Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/icon-button-play-slider.pdf => Source/waweform-icon-button-play-slider.pdf (100%) diff --git a/Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/Contents.json b/Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/Contents.json deleted file mode 100644 index 611046d..0000000 --- a/Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "icon-button-play-slider.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Example/Waveform.xcodeproj/project.pbxproj b/Example/Waveform.xcodeproj/project.pbxproj index 2745a56..8cc51a8 100644 --- a/Example/Waveform.xcodeproj/project.pbxproj +++ b/Example/Waveform.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 27FC62211DE7366A00D08082 /* waweform-icon-button-play-slider.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62201DE7366A00D08082 /* waweform-icon-button-play-slider.pdf */; }; 8BD39F7C1CC5648B005E8947 /* AudioSamplesReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */; }; 8BD39F7D1CC5648B005E8947 /* ScalableChannelsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */; }; 8BD39F7E1CC5648B005E8947 /* DVGAudioWaveformDiagram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F641CC5648B005E8947 /* DVGAudioWaveformDiagram.swift */; }; @@ -42,6 +43,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 27FC62201DE7366A00D08082 /* waweform-icon-button-play-slider.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "waweform-icon-button-play-slider.pdf"; sourceTree = ""; }; 8B3F34EE1C243BA6006A4B67 /* Waveform.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Waveform.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioSamplesReader.swift; sourceTree = ""; }; 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScalableChannelsContainer.swift; sourceTree = ""; }; @@ -89,11 +91,20 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 27FC621B1DE732FE00D08082 /* Resources */ = { + isa = PBXGroup; + children = ( + 27FC62201DE7366A00D08082 /* waweform-icon-button-play-slider.pdf */, + ); + name = Resources; + path = ../Source; + sourceTree = ""; + }; 8B3F34E51C243BA6006A4B67 = { isa = PBXGroup; children = ( + 27FC621B1DE732FE00D08082 /* Resources */, 8BD39F601CC5648B005E8947 /* Source */, - 8BD39ED91CC559FA005E8947 /* Waveform */, 8B3F34EF1C243BA6006A4B67 /* Products */, ); sourceTree = ""; @@ -119,12 +130,14 @@ 8BD39F9E1CC565E9005E8947 /* ViewController.swift */, 8BD39F9F1CC565E9005E8947 /* Waveform-Bridging-Header.h */, ); - path = Waveform; + name = Waveform; + path = ../Example/Waveform; sourceTree = ""; }; 8BD39F601CC5648B005E8947 /* Source */ = { isa = PBXGroup; children = ( + 8BD39ED91CC559FA005E8947 /* Waveform */, 8BD39F611CC5648B005E8947 /* Data Source */, 8BD39F641CC5648B005E8947 /* DVGAudioWaveformDiagram.swift */, 8BD39F651CC5648B005E8947 /* DVGAudioWaveformDiagramModel.swift */, @@ -255,6 +268,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 27FC62211DE7366A00D08082 /* waweform-icon-button-play-slider.pdf in Resources */, 8BD39FA41CC565E9005E8947 /* Info.plist in Resources */, 8BD39FA31CC565E9005E8947 /* Main.storyboard in Resources */, 8BD39FA11CC565E9005E8947 /* Assets.xcassets in Resources */, diff --git a/Source/View/PlaybackPositionView.swift b/Source/View/PlaybackPositionView.swift index d771f6e..a5273e9 100644 --- a/Source/View/PlaybackPositionView.swift +++ b/Source/View/PlaybackPositionView.swift @@ -11,7 +11,7 @@ import UIKit public class PlaybackPositionView: UIView { - let cursor = UIImageView(image: UIImage(named: "icon-button-play-slider")) + let cursor = UIImageView(image: UIImage(named: "waweform-icon-button-play-slider")) init() { super.init(frame: .zero) diff --git a/Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/icon-button-play-slider.pdf b/Source/waweform-icon-button-play-slider.pdf similarity index 100% rename from Example/SRC/Assets.xcassets/icon-button-play-slider.imageset/icon-button-play-slider.pdf rename to Source/waweform-icon-button-play-slider.pdf diff --git a/Waveform.podspec b/Waveform.podspec index 67d1251..2be2276 100644 --- a/Waveform.podspec +++ b/Waveform.podspec @@ -15,4 +15,5 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/denivip/Waveform.git", :tag => "0.0.2" } s.source_files = "Source/**/*.{swift}" s.frameworks = "Foundation", "UIKit", "AVFoundation", "CoreMedia" + s.resources = "Resources/**/*.pdf" end \ No newline at end of file From 0ccb52e916f0882c38236b4078efa68e7a94af16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Thu, 24 Nov 2016 17:58:34 +0300 Subject: [PATCH 11/31] Podspec file updated --- Waveform.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Waveform.podspec b/Waveform.podspec index 2be2276..fbd7073 100644 --- a/Waveform.podspec +++ b/Waveform.podspec @@ -15,5 +15,5 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/denivip/Waveform.git", :tag => "0.0.2" } s.source_files = "Source/**/*.{swift}" s.frameworks = "Foundation", "UIKit", "AVFoundation", "CoreMedia" - s.resources = "Resources/**/*.pdf" + s.resources = "Resources/*.pdf" end \ No newline at end of file From 83988be5c295396662f82e6094fcbd983eae545e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Thu, 24 Nov 2016 18:10:28 +0300 Subject: [PATCH 12/31] Icon play slider added --- Resources/waweform-icon-button-play-slider.pdf | Bin 0 -> 6407 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Resources/waweform-icon-button-play-slider.pdf diff --git a/Resources/waweform-icon-button-play-slider.pdf b/Resources/waweform-icon-button-play-slider.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c3285a63a968543dc421797cf81f5ca24b4661ec GIT binary patch literal 6407 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 UP?# Date: Thu, 24 Nov 2016 18:13:23 +0300 Subject: [PATCH 13/31] Podspec adjusted --- Waveform.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Waveform.podspec b/Waveform.podspec index fbd7073..2be2276 100644 --- a/Waveform.podspec +++ b/Waveform.podspec @@ -15,5 +15,5 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/denivip/Waveform.git", :tag => "0.0.2" } s.source_files = "Source/**/*.{swift}" s.frameworks = "Foundation", "UIKit", "AVFoundation", "CoreMedia" - s.resources = "Resources/*.pdf" + s.resources = "Resources/**/*.pdf" end \ No newline at end of file From c975ccb895df27c7987eb2de6838e1e86b2fe826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Thu, 24 Nov 2016 20:17:19 +0300 Subject: [PATCH 14/31] Images changes to png --- Example/Waveform.xcodeproj/project.pbxproj | 4 ---- Resources/waweform-icon-button-play-slider.pdf | Bin 6407 -> 0 bytes Source/waweform-icon-button-play-slider.pdf | Bin 6407 -> 0 bytes Waveform.podspec | 2 +- 4 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 Resources/waweform-icon-button-play-slider.pdf delete mode 100644 Source/waweform-icon-button-play-slider.pdf diff --git a/Example/Waveform.xcodeproj/project.pbxproj b/Example/Waveform.xcodeproj/project.pbxproj index 8cc51a8..09cdabf 100644 --- a/Example/Waveform.xcodeproj/project.pbxproj +++ b/Example/Waveform.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 27FC62211DE7366A00D08082 /* waweform-icon-button-play-slider.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62201DE7366A00D08082 /* waweform-icon-button-play-slider.pdf */; }; 8BD39F7C1CC5648B005E8947 /* AudioSamplesReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */; }; 8BD39F7D1CC5648B005E8947 /* ScalableChannelsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */; }; 8BD39F7E1CC5648B005E8947 /* DVGAudioWaveformDiagram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F641CC5648B005E8947 /* DVGAudioWaveformDiagram.swift */; }; @@ -43,7 +42,6 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 27FC62201DE7366A00D08082 /* waweform-icon-button-play-slider.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "waweform-icon-button-play-slider.pdf"; sourceTree = ""; }; 8B3F34EE1C243BA6006A4B67 /* Waveform.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Waveform.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioSamplesReader.swift; sourceTree = ""; }; 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScalableChannelsContainer.swift; sourceTree = ""; }; @@ -94,7 +92,6 @@ 27FC621B1DE732FE00D08082 /* Resources */ = { isa = PBXGroup; children = ( - 27FC62201DE7366A00D08082 /* waweform-icon-button-play-slider.pdf */, ); name = Resources; path = ../Source; @@ -268,7 +265,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 27FC62211DE7366A00D08082 /* waweform-icon-button-play-slider.pdf in Resources */, 8BD39FA41CC565E9005E8947 /* Info.plist in Resources */, 8BD39FA31CC565E9005E8947 /* Main.storyboard in Resources */, 8BD39FA11CC565E9005E8947 /* Assets.xcassets in Resources */, diff --git a/Resources/waweform-icon-button-play-slider.pdf b/Resources/waweform-icon-button-play-slider.pdf deleted file mode 100644 index c3285a63a968543dc421797cf81f5ca24b4661ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6407 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 UP?#BV;haJB}A5MOG2V6NedMzDv>RF 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 UP?# "https://github.com/denivip/Waveform.git", :tag => "0.0.2" } s.source_files = "Source/**/*.{swift}" s.frameworks = "Foundation", "UIKit", "AVFoundation", "CoreMedia" - s.resources = "Resources/**/*.pdf" + s.resources = "Resources/**/*.png" end \ No newline at end of file From da12534463583cabe106b595c304395efe20bc2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Thu, 24 Nov 2016 20:32:23 +0300 Subject: [PATCH 15/31] Images added to project --- Example/Waveform.xcodeproj/project.pbxproj | 8 ++++++++ Source/icon-button-play-slider.png | Bin 0 -> 485 bytes Source/icon-button-selection.png | Bin 0 -> 848 bytes 3 files changed, 8 insertions(+) create mode 100644 Source/icon-button-play-slider.png create mode 100644 Source/icon-button-selection.png diff --git a/Example/Waveform.xcodeproj/project.pbxproj b/Example/Waveform.xcodeproj/project.pbxproj index 09cdabf..00cba91 100644 --- a/Example/Waveform.xcodeproj/project.pbxproj +++ b/Example/Waveform.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 27FC62241DE75B8B00D08082 /* icon-button-play-slider.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62221DE75B8B00D08082 /* icon-button-play-slider.png */; }; + 27FC62251DE75B8B00D08082 /* icon-button-selection.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62231DE75B8B00D08082 /* icon-button-selection.png */; }; 8BD39F7C1CC5648B005E8947 /* AudioSamplesReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */; }; 8BD39F7D1CC5648B005E8947 /* ScalableChannelsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */; }; 8BD39F7E1CC5648B005E8947 /* DVGAudioWaveformDiagram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F641CC5648B005E8947 /* DVGAudioWaveformDiagram.swift */; }; @@ -42,6 +44,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 27FC62221DE75B8B00D08082 /* icon-button-play-slider.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-button-play-slider.png"; sourceTree = ""; }; + 27FC62231DE75B8B00D08082 /* icon-button-selection.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-button-selection.png"; sourceTree = ""; }; 8B3F34EE1C243BA6006A4B67 /* Waveform.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Waveform.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioSamplesReader.swift; sourceTree = ""; }; 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScalableChannelsContainer.swift; sourceTree = ""; }; @@ -92,6 +96,8 @@ 27FC621B1DE732FE00D08082 /* Resources */ = { isa = PBXGroup; children = ( + 27FC62221DE75B8B00D08082 /* icon-button-play-slider.png */, + 27FC62231DE75B8B00D08082 /* icon-button-selection.png */, ); name = Resources; path = ../Source; @@ -268,7 +274,9 @@ 8BD39FA41CC565E9005E8947 /* Info.plist in Resources */, 8BD39FA31CC565E9005E8947 /* Main.storyboard in Resources */, 8BD39FA11CC565E9005E8947 /* Assets.xcassets in Resources */, + 27FC62251DE75B8B00D08082 /* icon-button-selection.png in Resources */, 8BD39FA21CC565E9005E8947 /* LaunchScreen.storyboard in Resources */, + 27FC62241DE75B8B00D08082 /* icon-button-play-slider.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/icon-button-play-slider.png b/Source/icon-button-play-slider.png new file mode 100644 index 0000000000000000000000000000000000000000..3102aecad22ddc28f65c6dbc92c809e65b281d72 GIT binary patch literal 485 zcmVPx$pGibPR7ef&mt9W7Fc5^>hQA^Nf(LR1&cQKyDG&#N6Y$)gpz00ag;Xd60! zgEq0tEqCp6;Yzp>_|70FzJ;}r37bqW=E4>rG0xi0 bX!FrOji#K}37p8o00000NkvXXu0mjffLPx( literal 0 HcmV?d00001 diff --git a/Source/icon-button-selection.png b/Source/icon-button-selection.png new file mode 100644 index 0000000000000000000000000000000000000000..9454b986936dcfc59968d381da01a62472890ed7 GIT binary patch literal 848 zcmV-W1F!svP)Px&3Q0skR9Fe^n9q(9K@i6Ir@I=(KM66Oh>3@dXXDX$*caFr@D=pv)5rlHLe6T! zVJ}8Ka4~@Z!JEVdRur&)&3xm`z+{*m4;-eFZ>qbx>Z|VR-kqTfgzjKV%J!( z9pheD+Wb$F*AR)_6RAwOB09SF6>< zIz|}7$9!KCL#zP~CaOtUb0bP}&AK-mjmF7*K7Sv>9cw0rSU3!DZ6(9tl2ohJ`?J~X zLo8dufW>}-05HZQz>5w6#4)Ku@Q3C0WHQQ5MPAgG1$~~g~0WH$_V3=ixh^xSl2DHe-QjpVywVwmTL;mRe=OP80iv96E(w0rBZn@91g!E+*!m94+ewJaKPnp!tH*9vnuWcxKep!cy@Yv`m*2ee~o2} z86bvOI6N*m;dYhd!3~GIqA~r%@Vs0upS4=8#%MJ9X4hnwG2Cm$@M$)iZ;2t+;|N{R z@P-9S#xidk?t0*@%S}q~7R0)~um^t(zYH@2Z_^(hewyY4|2C|6jq7x}4pD1m&o61hlwC>i}=TjNnJV(h`T a@Anse|7UFB*eYEB0000 Date: Thu, 24 Nov 2016 21:00:40 +0300 Subject: [PATCH 16/31] Images moved to resources folder --- {Source => Resources}/icon-button-play-slider.png | Bin {Source => Resources}/icon-button-selection.png | Bin 2 files changed, 0 insertions(+), 0 deletions(-) rename {Source => Resources}/icon-button-play-slider.png (100%) rename {Source => Resources}/icon-button-selection.png (100%) diff --git a/Source/icon-button-play-slider.png b/Resources/icon-button-play-slider.png similarity index 100% rename from Source/icon-button-play-slider.png rename to Resources/icon-button-play-slider.png diff --git a/Source/icon-button-selection.png b/Resources/icon-button-selection.png similarity index 100% rename from Source/icon-button-selection.png rename to Resources/icon-button-selection.png From 2b9a0955d0cb3a6e73b7c93c4ca935a8f6661a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Thu, 24 Nov 2016 21:01:35 +0300 Subject: [PATCH 17/31] Project updated according to images relocation --- Example/Waveform.xcodeproj/project.pbxproj | 16 ++++++++-------- Source/icon-button-play-slider.png | Bin 0 -> 485 bytes Source/icon-button-selection.png | Bin 0 -> 848 bytes 3 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 Source/icon-button-play-slider.png create mode 100644 Source/icon-button-selection.png diff --git a/Example/Waveform.xcodeproj/project.pbxproj b/Example/Waveform.xcodeproj/project.pbxproj index 00cba91..713d4de 100644 --- a/Example/Waveform.xcodeproj/project.pbxproj +++ b/Example/Waveform.xcodeproj/project.pbxproj @@ -7,8 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 27FC62241DE75B8B00D08082 /* icon-button-play-slider.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62221DE75B8B00D08082 /* icon-button-play-slider.png */; }; - 27FC62251DE75B8B00D08082 /* icon-button-selection.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62231DE75B8B00D08082 /* icon-button-selection.png */; }; + 27FC62281DE7626400D08082 /* icon-button-play-slider.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62261DE7626400D08082 /* icon-button-play-slider.png */; }; + 27FC62291DE7626400D08082 /* icon-button-selection.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62271DE7626400D08082 /* icon-button-selection.png */; }; 8BD39F7C1CC5648B005E8947 /* AudioSamplesReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */; }; 8BD39F7D1CC5648B005E8947 /* ScalableChannelsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */; }; 8BD39F7E1CC5648B005E8947 /* DVGAudioWaveformDiagram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F641CC5648B005E8947 /* DVGAudioWaveformDiagram.swift */; }; @@ -44,8 +44,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 27FC62221DE75B8B00D08082 /* icon-button-play-slider.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-button-play-slider.png"; sourceTree = ""; }; - 27FC62231DE75B8B00D08082 /* icon-button-selection.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-button-selection.png"; sourceTree = ""; }; + 27FC62261DE7626400D08082 /* icon-button-play-slider.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-button-play-slider.png"; sourceTree = ""; }; + 27FC62271DE7626400D08082 /* icon-button-selection.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-button-selection.png"; sourceTree = ""; }; 8B3F34EE1C243BA6006A4B67 /* Waveform.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Waveform.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioSamplesReader.swift; sourceTree = ""; }; 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScalableChannelsContainer.swift; sourceTree = ""; }; @@ -96,8 +96,8 @@ 27FC621B1DE732FE00D08082 /* Resources */ = { isa = PBXGroup; children = ( - 27FC62221DE75B8B00D08082 /* icon-button-play-slider.png */, - 27FC62231DE75B8B00D08082 /* icon-button-selection.png */, + 27FC62261DE7626400D08082 /* icon-button-play-slider.png */, + 27FC62271DE7626400D08082 /* icon-button-selection.png */, ); name = Resources; path = ../Source; @@ -274,9 +274,9 @@ 8BD39FA41CC565E9005E8947 /* Info.plist in Resources */, 8BD39FA31CC565E9005E8947 /* Main.storyboard in Resources */, 8BD39FA11CC565E9005E8947 /* Assets.xcassets in Resources */, - 27FC62251DE75B8B00D08082 /* icon-button-selection.png in Resources */, + 27FC62291DE7626400D08082 /* icon-button-selection.png in Resources */, 8BD39FA21CC565E9005E8947 /* LaunchScreen.storyboard in Resources */, - 27FC62241DE75B8B00D08082 /* icon-button-play-slider.png in Resources */, + 27FC62281DE7626400D08082 /* icon-button-play-slider.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/icon-button-play-slider.png b/Source/icon-button-play-slider.png new file mode 100644 index 0000000000000000000000000000000000000000..3102aecad22ddc28f65c6dbc92c809e65b281d72 GIT binary patch literal 485 zcmVPx$pGibPR7ef&mt9W7Fc5^>hQA^Nf(LR1&cQKyDG&#N6Y$)gpz00ag;Xd60! zgEq0tEqCp6;Yzp>_|70FzJ;}r37bqW=E4>rG0xi0 bX!FrOji#K}37p8o00000NkvXXu0mjffLPx( literal 0 HcmV?d00001 diff --git a/Source/icon-button-selection.png b/Source/icon-button-selection.png new file mode 100644 index 0000000000000000000000000000000000000000..9454b986936dcfc59968d381da01a62472890ed7 GIT binary patch literal 848 zcmV-W1F!svP)Px&3Q0skR9Fe^n9q(9K@i6Ir@I=(KM66Oh>3@dXXDX$*caFr@D=pv)5rlHLe6T! zVJ}8Ka4~@Z!JEVdRur&)&3xm`z+{*m4;-eFZ>qbx>Z|VR-kqTfgzjKV%J!( z9pheD+Wb$F*AR)_6RAwOB09SF6>< zIz|}7$9!KCL#zP~CaOtUb0bP}&AK-mjmF7*K7Sv>9cw0rSU3!DZ6(9tl2ohJ`?J~X zLo8dufW>}-05HZQz>5w6#4)Ku@Q3C0WHQQ5MPAgG1$~~g~0WH$_V3=ixh^xSl2DHe-QjpVywVwmTL;mRe=OP80iv96E(w0rBZn@91g!E+*!m94+ewJaKPnp!tH*9vnuWcxKep!cy@Yv`m*2ee~o2} z86bvOI6N*m;dYhd!3~GIqA~r%@Vs0upS4=8#%MJ9X4hnwG2Cm$@M$)iZ;2t+;|N{R z@P-9S#xidk?t0*@%S}q~7R0)~um^t(zYH@2Z_^(hewyY4|2C|6jq7x}4pD1m&o61hlwC>i}=TjNnJV(h`T a@Anse|7UFB*eYEB0000 Date: Thu, 24 Nov 2016 21:21:45 +0300 Subject: [PATCH 18/31] Images renamed --- Example/Waveform.xcodeproj/project.pbxproj | 16 ++++++++-------- Source/View/PlaybackPositionView.swift | 2 +- ...png => waweform-icon-button-play-slider.png} | Bin ...n.png => waweform-icon-button-selection.png} | Bin 4 files changed, 9 insertions(+), 9 deletions(-) rename Source/{icon-button-play-slider.png => waweform-icon-button-play-slider.png} (100%) rename Source/{icon-button-selection.png => waweform-icon-button-selection.png} (100%) diff --git a/Example/Waveform.xcodeproj/project.pbxproj b/Example/Waveform.xcodeproj/project.pbxproj index 713d4de..9f66e5f 100644 --- a/Example/Waveform.xcodeproj/project.pbxproj +++ b/Example/Waveform.xcodeproj/project.pbxproj @@ -7,8 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 27FC62281DE7626400D08082 /* icon-button-play-slider.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62261DE7626400D08082 /* icon-button-play-slider.png */; }; - 27FC62291DE7626400D08082 /* icon-button-selection.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62271DE7626400D08082 /* icon-button-selection.png */; }; + 27FC62281DE7626400D08082 /* waweform-icon-button-play-slider.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62261DE7626400D08082 /* waweform-icon-button-play-slider.png */; }; + 27FC62291DE7626400D08082 /* waweform-icon-button-selection.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62271DE7626400D08082 /* waweform-icon-button-selection.png */; }; 8BD39F7C1CC5648B005E8947 /* AudioSamplesReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */; }; 8BD39F7D1CC5648B005E8947 /* ScalableChannelsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */; }; 8BD39F7E1CC5648B005E8947 /* DVGAudioWaveformDiagram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F641CC5648B005E8947 /* DVGAudioWaveformDiagram.swift */; }; @@ -44,8 +44,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 27FC62261DE7626400D08082 /* icon-button-play-slider.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-button-play-slider.png"; sourceTree = ""; }; - 27FC62271DE7626400D08082 /* icon-button-selection.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-button-selection.png"; sourceTree = ""; }; + 27FC62261DE7626400D08082 /* waweform-icon-button-play-slider.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "waweform-icon-button-play-slider.png"; sourceTree = ""; }; + 27FC62271DE7626400D08082 /* waweform-icon-button-selection.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "waweform-icon-button-selection.png"; sourceTree = ""; }; 8B3F34EE1C243BA6006A4B67 /* Waveform.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Waveform.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioSamplesReader.swift; sourceTree = ""; }; 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScalableChannelsContainer.swift; sourceTree = ""; }; @@ -96,8 +96,8 @@ 27FC621B1DE732FE00D08082 /* Resources */ = { isa = PBXGroup; children = ( - 27FC62261DE7626400D08082 /* icon-button-play-slider.png */, - 27FC62271DE7626400D08082 /* icon-button-selection.png */, + 27FC62261DE7626400D08082 /* waweform-icon-button-play-slider.png */, + 27FC62271DE7626400D08082 /* waweform-icon-button-selection.png */, ); name = Resources; path = ../Source; @@ -274,9 +274,9 @@ 8BD39FA41CC565E9005E8947 /* Info.plist in Resources */, 8BD39FA31CC565E9005E8947 /* Main.storyboard in Resources */, 8BD39FA11CC565E9005E8947 /* Assets.xcassets in Resources */, - 27FC62291DE7626400D08082 /* icon-button-selection.png in Resources */, + 27FC62291DE7626400D08082 /* waweform-icon-button-selection.png in Resources */, 8BD39FA21CC565E9005E8947 /* LaunchScreen.storyboard in Resources */, - 27FC62281DE7626400D08082 /* icon-button-play-slider.png in Resources */, + 27FC62281DE7626400D08082 /* waweform-icon-button-play-slider.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/View/PlaybackPositionView.swift b/Source/View/PlaybackPositionView.swift index a5273e9..6372345 100644 --- a/Source/View/PlaybackPositionView.swift +++ b/Source/View/PlaybackPositionView.swift @@ -11,7 +11,7 @@ import UIKit public class PlaybackPositionView: UIView { - let cursor = UIImageView(image: UIImage(named: "waweform-icon-button-play-slider")) + let cursor = UIImageView(image: UIImage(named: "waweform-icon-button-play-slider", in: Bundle(for: PlaybackPositionView.self), compatibleWith: nil)!) init() { super.init(frame: .zero) diff --git a/Source/icon-button-play-slider.png b/Source/waweform-icon-button-play-slider.png similarity index 100% rename from Source/icon-button-play-slider.png rename to Source/waweform-icon-button-play-slider.png diff --git a/Source/icon-button-selection.png b/Source/waweform-icon-button-selection.png similarity index 100% rename from Source/icon-button-selection.png rename to Source/waweform-icon-button-selection.png From 4c1bec80b656aa2df76158e761ec91c5d53273d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Thu, 24 Nov 2016 21:27:10 +0300 Subject: [PATCH 19/31] Images location in project fixed --- Example/Waveform.xcodeproj/project.pbxproj | 16 ++++++++-------- Resources/icon-button-play-slider.png | Bin 485 -> 0 bytes Resources/icon-button-selection.png | Bin 848 -> 0 bytes .../waweform-icon-button-play-slider.png | Bin .../waweform-icon-button-selection.png | Bin 5 files changed, 8 insertions(+), 8 deletions(-) delete mode 100644 Resources/icon-button-play-slider.png delete mode 100644 Resources/icon-button-selection.png rename {Source => Resources}/waweform-icon-button-play-slider.png (100%) rename {Source => Resources}/waweform-icon-button-selection.png (100%) diff --git a/Example/Waveform.xcodeproj/project.pbxproj b/Example/Waveform.xcodeproj/project.pbxproj index 9f66e5f..c203f67 100644 --- a/Example/Waveform.xcodeproj/project.pbxproj +++ b/Example/Waveform.xcodeproj/project.pbxproj @@ -7,8 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 27FC62281DE7626400D08082 /* waweform-icon-button-play-slider.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62261DE7626400D08082 /* waweform-icon-button-play-slider.png */; }; - 27FC62291DE7626400D08082 /* waweform-icon-button-selection.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC62271DE7626400D08082 /* waweform-icon-button-selection.png */; }; + 27FC622C1DE7686900D08082 /* waweform-icon-button-play-slider.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC622A1DE7686900D08082 /* waweform-icon-button-play-slider.png */; }; + 27FC622D1DE7686900D08082 /* waweform-icon-button-selection.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FC622B1DE7686900D08082 /* waweform-icon-button-selection.png */; }; 8BD39F7C1CC5648B005E8947 /* AudioSamplesReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */; }; 8BD39F7D1CC5648B005E8947 /* ScalableChannelsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */; }; 8BD39F7E1CC5648B005E8947 /* DVGAudioWaveformDiagram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD39F641CC5648B005E8947 /* DVGAudioWaveformDiagram.swift */; }; @@ -44,8 +44,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 27FC62261DE7626400D08082 /* waweform-icon-button-play-slider.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "waweform-icon-button-play-slider.png"; sourceTree = ""; }; - 27FC62271DE7626400D08082 /* waweform-icon-button-selection.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "waweform-icon-button-selection.png"; sourceTree = ""; }; + 27FC622A1DE7686900D08082 /* waweform-icon-button-play-slider.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "waweform-icon-button-play-slider.png"; path = "../Resources/waweform-icon-button-play-slider.png"; sourceTree = ""; }; + 27FC622B1DE7686900D08082 /* waweform-icon-button-selection.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "waweform-icon-button-selection.png"; path = "../Resources/waweform-icon-button-selection.png"; sourceTree = ""; }; 8B3F34EE1C243BA6006A4B67 /* Waveform.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Waveform.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8BD39F621CC5648B005E8947 /* AudioSamplesReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioSamplesReader.swift; sourceTree = ""; }; 8BD39F631CC5648B005E8947 /* ScalableChannelsContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScalableChannelsContainer.swift; sourceTree = ""; }; @@ -96,8 +96,8 @@ 27FC621B1DE732FE00D08082 /* Resources */ = { isa = PBXGroup; children = ( - 27FC62261DE7626400D08082 /* waweform-icon-button-play-slider.png */, - 27FC62271DE7626400D08082 /* waweform-icon-button-selection.png */, + 27FC622A1DE7686900D08082 /* waweform-icon-button-play-slider.png */, + 27FC622B1DE7686900D08082 /* waweform-icon-button-selection.png */, ); name = Resources; path = ../Source; @@ -273,10 +273,10 @@ files = ( 8BD39FA41CC565E9005E8947 /* Info.plist in Resources */, 8BD39FA31CC565E9005E8947 /* Main.storyboard in Resources */, + 27FC622C1DE7686900D08082 /* waweform-icon-button-play-slider.png in Resources */, + 27FC622D1DE7686900D08082 /* waweform-icon-button-selection.png in Resources */, 8BD39FA11CC565E9005E8947 /* Assets.xcassets in Resources */, - 27FC62291DE7626400D08082 /* waweform-icon-button-selection.png in Resources */, 8BD39FA21CC565E9005E8947 /* LaunchScreen.storyboard in Resources */, - 27FC62281DE7626400D08082 /* waweform-icon-button-play-slider.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Resources/icon-button-play-slider.png b/Resources/icon-button-play-slider.png deleted file mode 100644 index 3102aecad22ddc28f65c6dbc92c809e65b281d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 485 zcmVPx$pGibPR7ef&mt9W7Fc5^>hQA^Nf(LR1&cQKyDG&#N6Y$)gpz00ag;Xd60! zgEq0tEqCp6;Yzp>_|70FzJ;}r37bqW=E4>rG0xi0 bX!FrOji#K}37p8o00000NkvXXu0mjffLPx( diff --git a/Resources/icon-button-selection.png b/Resources/icon-button-selection.png deleted file mode 100644 index 9454b986936dcfc59968d381da01a62472890ed7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 848 zcmV-W1F!svP)Px&3Q0skR9Fe^n9q(9K@i6Ir@I=(KM66Oh>3@dXXDX$*caFr@D=pv)5rlHLe6T! zVJ}8Ka4~@Z!JEVdRur&)&3xm`z+{*m4;-eFZ>qbx>Z|VR-kqTfgzjKV%J!( z9pheD+Wb$F*AR)_6RAwOB09SF6>< zIz|}7$9!KCL#zP~CaOtUb0bP}&AK-mjmF7*K7Sv>9cw0rSU3!DZ6(9tl2ohJ`?J~X zLo8dufW>}-05HZQz>5w6#4)Ku@Q3C0WHQQ5MPAgG1$~~g~0WH$_V3=ixh^xSl2DHe-QjpVywVwmTL;mRe=OP80iv96E(w0rBZn@91g!E+*!m94+ewJaKPnp!tH*9vnuWcxKep!cy@Yv`m*2ee~o2} z86bvOI6N*m;dYhd!3~GIqA~r%@Vs0upS4=8#%MJ9X4hnwG2Cm$@M$)iZ;2t+;|N{R z@P-9S#xidk?t0*@%S}q~7R0)~um^t(zYH@2Z_^(hewyY4|2C|6jq7x}4pD1m&o61hlwC>i}=TjNnJV(h`T a@Anse|7UFB*eYEB0000 Date: Thu, 24 Nov 2016 21:37:05 +0300 Subject: [PATCH 20/31] Fixed playback position view rules for cursor position --- Source/View/PlaybackPositionView.swift | 3 ++- Waveform.podspec | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/View/PlaybackPositionView.swift b/Source/View/PlaybackPositionView.swift index 6372345..3b2bf14 100644 --- a/Source/View/PlaybackPositionView.swift +++ b/Source/View/PlaybackPositionView.swift @@ -28,7 +28,8 @@ class PlaybackPositionView: UIView { func positionCursor(){ guard let relativePosition = self.position, - relativePosition < 0 || relativePosition > 1 + relativePosition >= 0, + relativePosition <= 1 else { cursor.isHidden = true return diff --git a/Waveform.podspec b/Waveform.podspec index 4fbbbad..c2c31fb 100644 --- a/Waveform.podspec +++ b/Waveform.podspec @@ -5,7 +5,7 @@ Pod::Spec.new do |s| s.summary = "DENIVIP Media" s.requires_arc = true - s.version = "0.0.2" + s.version = "0.0.3" s.license = { :type => "MIT", :file => "LICENSE" } s.author = { "Anton Belousov" => "belousov@denivip.ru" } From 62e002e3e4bfbbeeb4fdf63ecf4c04c2df151c4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Thu, 24 Nov 2016 21:49:31 +0300 Subject: [PATCH 21/31] Slider size adjusted for 2x resolution --- Source/View/PlaybackPositionView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/View/PlaybackPositionView.swift b/Source/View/PlaybackPositionView.swift index 3b2bf14..3ce507b 100644 --- a/Source/View/PlaybackPositionView.swift +++ b/Source/View/PlaybackPositionView.swift @@ -16,7 +16,7 @@ class PlaybackPositionView: UIView { init() { super.init(frame: .zero) self.isOpaque = false - cursor.frame = CGRect(x: 0, y: 0, width: cursor.image!.size.width, height: cursor.image!.size.height); + cursor.frame = CGRect(x: 0, y: 0, width: cursor.image!.size.width/2.0, height: cursor.image!.size.height/2.0); cursor.isHidden = true addSubview(cursor) } From aad6a00e1762f395a3e9aaa976138e920fff0856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Fri, 25 Nov 2016 17:26:00 +0300 Subject: [PATCH 22/31] Sliders added to waweform selection --- Source/DVGAudioWaveformDiagram.swift | 10 ++++++ .../ScalableChannelsContainer.swift | 2 +- Source/View/SelectionView.swift | 33 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/Source/DVGAudioWaveformDiagram.swift b/Source/DVGAudioWaveformDiagram.swift index 2b3ea26..d619ac6 100644 --- a/Source/DVGAudioWaveformDiagram.swift +++ b/Source/DVGAudioWaveformDiagram.swift @@ -12,6 +12,7 @@ import UIKit public class DVGAudioWaveformDiagram: UIView { + //MARK: - Properties var panToSelect: UIPanGestureRecognizer! var tapToSelect: UILongPressGestureRecognizer! var pan: UIPanGestureRecognizer! @@ -32,6 +33,7 @@ class DVGAudioWaveformDiagram: UIView { } } + //MARK: - Initialization override init(frame: CGRect) { super.init(frame: frame) self.setup() @@ -99,6 +101,8 @@ class DVGAudioWaveformDiagram: UIView { self.playbackPositionView = playbackPositionView } + + //MARK: - Gestures private var panStartLocation: CGFloat? func handlePanToSelect(_ pan: UIPanGestureRecognizer) { @@ -148,6 +152,8 @@ class DVGAudioWaveformDiagram: UIView { } } + + func handlePinch(_ gesture: UIPinchGestureRecognizer) { self.selectionView.selection = nil @@ -170,6 +176,8 @@ class DVGAudioWaveformDiagram: UIView { } } + + func handlePan(_ gesture: UIPanGestureRecognizer) { self.selectionView.selection = nil switch gesture.state { @@ -188,6 +196,8 @@ class DVGAudioWaveformDiagram: UIView { self.selection = l } + + var minSelectionWidth: CGFloat = 40.0 var playbackRelativePosition: CGFloat? = nil { didSet { diff --git a/Source/Data Source/ScalableChannelsContainer.swift b/Source/Data Source/ScalableChannelsContainer.swift index eefca03..6285fb2 100644 --- a/Source/Data Source/ScalableChannelsContainer.swift +++ b/Source/Data Source/ScalableChannelsContainer.swift @@ -128,7 +128,7 @@ class ScalableChannelsContainer: NSObject, ChannelSource, AudioSamplesHandler { } //MARK: - -//MARK: - Utility +//MARK: - Utility. Data Range. @objc public final diff --git a/Source/View/SelectionView.swift b/Source/View/SelectionView.swift index 019e4ed..91b1597 100644 --- a/Source/View/SelectionView.swift +++ b/Source/View/SelectionView.swift @@ -11,7 +11,13 @@ import UIKit @objc public class SelectionView: UIView { + + let sliderIcon = UIImage(named: "waweform-icon-button-selection", in: Bundle(for: SelectionView.self), compatibleWith: nil)! + var sliderSize: CGSize = .zero + let leftSlider = CALayer() + let rightSlider = CALayer() var selectionLayer: CALayer! + init() { super.init(frame: .zero) self.setup() @@ -25,6 +31,13 @@ class SelectionView: UIView { func setup() { self.setupSelectionLayer() self.backgroundColor = .clear + + leftSlider.contents = sliderIcon.cgImage + rightSlider.contents = sliderIcon.cgImage + sliderSize = CGSize(width: sliderIcon.size.width/2.0, height: sliderIcon.size.height/2.0) + + self.layer.addSublayer(leftSlider) + self.layer.addSublayer(rightSlider) } func setupSelectionLayer() { @@ -57,10 +70,30 @@ class SelectionView: UIView { let startLocation = self.bounds.width * CGFloat(dataRange.location) let selectionWidth = self.bounds.width * CGFloat(dataRange.length) + + if selectionWidth < sliderSize.width * 2 { + let opacity = max(Float((selectionWidth - sliderSize.width)/sliderSize.width), 0) + leftSlider.opacity = opacity + rightSlider.opacity = opacity + } else { + leftSlider.opacity = 1 + rightSlider.opacity = 1 + } + let frame = CGRect(x: startLocation, y: 0, width: selectionWidth, height: self.bounds.height) + let leftSliderFrame = CGRect(x: startLocation - sliderSize.width/2, + y: self.center.y - sliderSize.height/2, + width: sliderSize.width, + height: sliderSize.height) + let rightSliderFrame = CGRect(x: startLocation + selectionWidth - sliderSize.width/2, + y: self.center.y - sliderSize.height/2, + width: sliderSize.width, + height: sliderSize.height) CATransaction.begin() CATransaction.setDisableActions(true) self.selectionLayer.frame = frame + leftSlider.frame = leftSliderFrame + rightSlider.frame = rightSliderFrame CATransaction.commit() } } From d8242ca2514423845222f96ce38a84a95fe42f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Mon, 28 Nov 2016 16:30:51 +0300 Subject: [PATCH 23/31] Selection view ux updated. Sliders added. Tap to select removed. --- Source/DVGAudioWaveformDiagram.swift | 187 +++++++++++++++++++-------- 1 file changed, 133 insertions(+), 54 deletions(-) diff --git a/Source/DVGAudioWaveformDiagram.swift b/Source/DVGAudioWaveformDiagram.swift index d619ac6..2462e87 100644 --- a/Source/DVGAudioWaveformDiagram.swift +++ b/Source/DVGAudioWaveformDiagram.swift @@ -14,7 +14,6 @@ class DVGAudioWaveformDiagram: UIView { //MARK: - Properties var panToSelect: UIPanGestureRecognizer! - var tapToSelect: UILongPressGestureRecognizer! var pan: UIPanGestureRecognizer! var pinch: UIPinchGestureRecognizer! @@ -66,13 +65,6 @@ class DVGAudioWaveformDiagram: UIView { self.addGestureRecognizer(panToSelect) self.panToSelect = panToSelect panToSelect.maximumNumberOfTouches = 1 - - let tap = UILongPressGestureRecognizer(target: self, action: #selector(DVGAudioWaveformDiagram.handleTapToSelect(_:))) - tap.delegate = self - tap.minimumPressDuration = 0.08 - self.addGestureRecognizer(tap) - self.tapToSelect = tap - tap.numberOfTouchesRequired = 1 let pinch = UIPinchGestureRecognizer(target: self, action: #selector(DVGAudioWaveformDiagram.handlePinch(_:))) pinch.delegate = self @@ -104,14 +96,70 @@ class DVGAudioWaveformDiagram: UIView { //MARK: - Gestures private var panStartLocation: CGFloat? + private var panStartVelocityX: CGFloat? + + private var selectionUI : DataRange? { + if selection == nil { + return nil + } + + return DataRange(location: selection!.location * bounds.width.double , + length: selection!.length * bounds.width.double) + } + private var startSelection: DataRange? + + enum PanAction { + case moving, moveLeftSlider, moveRightSlider, selectNewArea + } + private var action: PanAction? + func handlePanToSelect(_ pan: UIPanGestureRecognizer) { + switch pan.state { case .began: + if self.panStartLocation == nil { self.panStartLocation = pan.location(in: self).x + self.panStartVelocityX = pan.velocity(in: self).x + } + + if (selectionUI == nil){ + self.configureSelectionFromPosition(panStartLocation!, + toPosition: pan.location(in: self).x, + anchor: panStartVelocityX!.double < 0.0 ? .right : .left ) + action = .selectNewArea + } else if selectionUI!.length > minSelectionWidth.double { + + let letftSliderRange = (selectionUI!.location - 25.0)..<(selectionUI!.location + 25.0) + if letftSliderRange.contains(panStartLocation!.double) { + action = .moveLeftSlider + } + + let righSliderRange = (selectionUI!.location + selectionUI!.length - 25.0)..<(selectionUI!.location + selectionUI!.length + 25.0) + if righSliderRange.contains(panStartLocation!.double) { + action = .moveRightSlider + } + + let middleRange = letftSliderRange.upperBound.. _endPosition && abs(endPosition - startPosition) < minSelectionWidth { + startPosition = endPosition - minSelectionWidth + } + if _startPosition <= _endPosition { + startPosition = startPosition - minSelectionWidth + } + break + + case .left: + if _startPosition < _endPosition && abs(endPosition - startPosition) < minSelectionWidth { + endPosition = startPosition + minSelectionWidth + } + if _startPosition >= _endPosition { + endPosition = endPosition + minSelectionWidth + } + break + } startPosition = max(0, startPosition) endPosition = min(endPosition, self.bounds.width) - let width = max(endPosition - startPosition, minSelectionWidth) + let width = endPosition - startPosition let range = DataRange( location: Double(startPosition / self.bounds.width), @@ -247,22 +336,12 @@ class DVGAudioWaveformDiagram: UIView { } extension DVGAudioWaveformDiagram: UIGestureRecognizerDelegate { - public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { - switch (gestureRecognizer, otherGestureRecognizer) { - case (panToSelect, tapToSelect): - fallthrough - case (tapToSelect, panToSelect): - return true - default: + public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool + { return false - } } override public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { - if gestureRecognizer == self.panToSelect { - self.tapToSelect.isEnabled = false - self.tapToSelect.isEnabled = true - } return true } } From d987ebd7b6c594b8a0d85345325997b032527017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Tue, 29 Nov 2016 15:48:03 +0300 Subject: [PATCH 24/31] Selection view fixes --- Source/DVGAudioWaveformDiagram.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/DVGAudioWaveformDiagram.swift b/Source/DVGAudioWaveformDiagram.swift index 2462e87..491af13 100644 --- a/Source/DVGAudioWaveformDiagram.swift +++ b/Source/DVGAudioWaveformDiagram.swift @@ -129,14 +129,16 @@ class DVGAudioWaveformDiagram: UIView { toPosition: pan.location(in: self).x, anchor: panStartVelocityX!.double < 0.0 ? .right : .left ) action = .selectNewArea - } else if selectionUI!.length > minSelectionWidth.double { + } else if selectionUI!.length >= minSelectionWidth.double - 1 { - let letftSliderRange = (selectionUI!.location - 25.0)..<(selectionUI!.location + 25.0) + let sliderHalfWidth = 20.0 + + let letftSliderRange = (selectionUI!.location - sliderHalfWidth)..<(selectionUI!.location + sliderHalfWidth) if letftSliderRange.contains(panStartLocation!.double) { action = .moveLeftSlider } - let righSliderRange = (selectionUI!.location + selectionUI!.length - 25.0)..<(selectionUI!.location + selectionUI!.length + 25.0) + let righSliderRange = (selectionUI!.location + selectionUI!.length - sliderHalfWidth)..<(selectionUI!.location + selectionUI!.length + sliderHalfWidth) if righSliderRange.contains(panStartLocation!.double) { action = .moveRightSlider } From df9db6bacce44e8043844846c3bd6f9617769461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Tue, 29 Nov 2016 15:49:43 +0300 Subject: [PATCH 25/31] Vesrion bump --- Example/SRC/Info.plist | 4 ++-- Waveform.podspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Example/SRC/Info.plist b/Example/SRC/Info.plist index 40c6215..c6c344a 100644 --- a/Example/SRC/Info.plist +++ b/Example/SRC/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0 + 3.1 CFBundleSignature ???? CFBundleVersion - 1 + 4 LSRequiresIPhoneOS UILaunchStoryboardName diff --git a/Waveform.podspec b/Waveform.podspec index c2c31fb..554b478 100644 --- a/Waveform.podspec +++ b/Waveform.podspec @@ -5,7 +5,7 @@ Pod::Spec.new do |s| s.summary = "DENIVIP Media" s.requires_arc = true - s.version = "0.0.3" + s.version = "3.1" s.license = { :type => "MIT", :file => "LICENSE" } s.author = { "Anton Belousov" => "belousov@denivip.ru" } From 54eb0830a8b66ef7e4d0729cd09cf5ae3e9afa11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Tue, 29 Nov 2016 15:51:44 +0300 Subject: [PATCH 26/31] Pod version 3.1.0 bump --- Waveform.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Waveform.podspec b/Waveform.podspec index 554b478..efbcaeb 100644 --- a/Waveform.podspec +++ b/Waveform.podspec @@ -5,14 +5,14 @@ Pod::Spec.new do |s| s.summary = "DENIVIP Media" s.requires_arc = true - s.version = "3.1" + s.version = "3.1.0" s.license = { :type => "MIT", :file => "LICENSE" } s.author = { "Anton Belousov" => "belousov@denivip.ru" } s.homepage = "https://github.com/denivip/Waveform" - s.source = { :git => "https://github.com/denivip/Waveform.git", :tag => "0.0.2" } + s.source = { :git => "https://github.com/denivip/Waveform.git", :tag => "3.1.0" } s.source_files = "Source/**/*.{swift}" s.frameworks = "Foundation", "UIKit", "AVFoundation", "CoreMedia" s.resources = "Resources/**/*.png" From b170c5dd9d69b5b3664f4b44926bf456dec05df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Fri, 2 Dec 2016 19:38:06 +0300 Subject: [PATCH 27/31] Added method for stop loading --- Source/DVGAudioWaveformDiagram.swift | 15 +++++++++++++-- Source/DVGWaveformView.swift | 4 ++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Source/DVGAudioWaveformDiagram.swift b/Source/DVGAudioWaveformDiagram.swift index 491af13..643a31e 100644 --- a/Source/DVGAudioWaveformDiagram.swift +++ b/Source/DVGAudioWaveformDiagram.swift @@ -97,7 +97,9 @@ class DVGAudioWaveformDiagram: UIView { //MARK: - Gestures private var panStartLocation: CGFloat? private var panStartVelocityX: CGFloat? - + + var delayedTask : DispatchWorkItem? + private var selectionUI : DataRange? { if selection == nil { return nil @@ -168,7 +170,16 @@ class DVGAudioWaveformDiagram: UIView { // notify delegate self.panStartLocation = nil if let selection = self.selection { - self.delegate?.diagramDidSelect(selection) + + if delayedTask != nil { + delayedTask!.cancel() + } + + delayedTask = DispatchWorkItem { [weak self] in + self?.delegate?.diagramDidSelect(selection) + } + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.7, execute: delayedTask!) } action = nil break diff --git a/Source/DVGWaveformView.swift b/Source/DVGWaveformView.swift index 7744836..158be21 100644 --- a/Source/DVGWaveformView.swift +++ b/Source/DVGWaveformView.swift @@ -101,6 +101,10 @@ class DVGWaveformController: NSObject { } } + func stopLoading(){ + self.diagram?.waveformDiagramView.stopSynchingWithDataSource() + } + public func addDataSource(_ dataSource: ChannelSource) { channelSourceMapper.addChannelSource(dataSource) From 08b3819be3d414202b1d867a1cc6dacf06260de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Fri, 2 Dec 2016 19:53:48 +0300 Subject: [PATCH 28/31] Cancel method for AudioSamplesReader implemented --- Source/DVGWaveformView.swift | 1 + Source/Data Source/AudioSamplesReader.swift | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Source/DVGWaveformView.swift b/Source/DVGWaveformView.swift index 158be21..e871722 100644 --- a/Source/DVGWaveformView.swift +++ b/Source/DVGWaveformView.swift @@ -102,6 +102,7 @@ class DVGWaveformController: NSObject { } func stopLoading(){ + self.samplesReader?.cancel() self.diagram?.waveformDiagramView.stopSynchingWithDataSource() } diff --git a/Source/Data Source/AudioSamplesReader.swift b/Source/Data Source/AudioSamplesReader.swift index 5103305..5ac4b47 100644 --- a/Source/Data Source/AudioSamplesReader.swift +++ b/Source/Data Source/AudioSamplesReader.swift @@ -31,6 +31,10 @@ class AudioSamplesReader: NSObject { var progress = Progress() + func cancel(){ + self.readingRoutine?.cancelReading() + } + func readAudioFormat(completionBlock: @escaping (AudioFormat?, SamplesReaderError?) -> ()) { dispatch_asynch_on_global_processing_queue { do { From 7d986d497641133903ed20713e8524b7d120de86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Thu, 8 Dec 2016 15:13:25 +0300 Subject: [PATCH 29/31] Selection on zoom fixed --- Source/DVGAudioWaveformDiagram.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/DVGAudioWaveformDiagram.swift b/Source/DVGAudioWaveformDiagram.swift index 643a31e..b758515 100644 --- a/Source/DVGAudioWaveformDiagram.swift +++ b/Source/DVGAudioWaveformDiagram.swift @@ -105,8 +105,10 @@ class DVGAudioWaveformDiagram: UIView { return nil } - return DataRange(location: selection!.location * bounds.width.double , - length: selection!.length * bounds.width.double) + let convertedSelection = selection?.convertToGeometry(dataSource!.geometry) + + return DataRange(location: convertedSelection!.location * bounds.width.double , + length: convertedSelection!.length * bounds.width.double) } private var startSelection: DataRange? From 1b5022c4046243f03146f08f8f40485cf844a379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Mon, 12 Dec 2016 19:44:29 +0300 Subject: [PATCH 30/31] Restarting sound loading after app enters foreground --- Source/Data Source/AudioSamplesReader.swift | 109 +++++++++++++------- Source/Utility/Error.swift | 1 + 2 files changed, 75 insertions(+), 35 deletions(-) diff --git a/Source/Data Source/AudioSamplesReader.swift b/Source/Data Source/AudioSamplesReader.swift index 5ac4b47..422303b 100644 --- a/Source/Data Source/AudioSamplesReader.swift +++ b/Source/Data Source/AudioSamplesReader.swift @@ -55,15 +55,15 @@ class AudioSamplesReader: NSObject { func readAudioFormat() throws -> AudioFormat { guard let formatDescription = try? soundFormatDescription() else { - throw SamplesReaderError.UnknownError(nil) + throw SamplesReaderError.UnknownError(nil) } -#if DEBUG - print("DEBUG Audio format description => \(formatDescription)") -#endif + #if DEBUG + print("DEBUG Audio format description => \(formatDescription)") + #endif guard let asbd = CMAudioFormatDescriptionGetStreamBasicDescription(formatDescription)?.pointee - else { - throw SamplesReaderError.UnknownError(nil) + else { + throw SamplesReaderError.UnknownError(nil) } let format = AudioFormat(samplesRate: Int(asbd.mSampleRate), bitsDepth: Int(asbd.mBitsPerChannel), numberOfChannels: Int(asbd.mChannelsPerFrame)) nativeAudioFormat = format @@ -83,8 +83,8 @@ class AudioSamplesReader: NSObject { } return formatDescription as! CMAudioFormatDescription } - - private func audioReadingSettings(forFormat audioFormat: AudioFormat) -> [String: AnyObject] { + + fileprivate static func audioReadingSettings(forFormat audioFormat: AudioFormat) -> [String: AnyObject] { return [ AVFormatIDKey : NSNumber(value: kAudioFormatLinearPCM), AVSampleRateKey : audioFormat.samplesRate as AnyObject, @@ -95,7 +95,7 @@ class AudioSamplesReader: NSObject { AVLinearPCMIsNonInterleaved : false as AnyObject ] } - + func readSamples(_ audioFormat: AudioFormat? = nil, completion: @escaping (Error?) -> ()) { dispatch_asynch_on_global_processing_queue({ try self.readSamples(audioFormat) }, onCatch: completion) @@ -108,30 +108,21 @@ class AudioSamplesReader: NSObject { try self.prepareForReading() try self.read() } - - private func prepareForReading() throws { - - let sound = try assetAudioTrack() - - let assetReader: AVAssetReader - do { - assetReader = try AVAssetReader(asset: asset) - } catch let error as NSError { - throw SamplesReaderError.UnknownError(error) - } - let settings = audioReadingSettings(forFormat: samplesReadAudioFormat) - - let readerOutput = AVAssetReaderTrackOutput(track: sound, outputSettings: settings) - - assetReader.add(readerOutput) - assetReader.timeRange = CMTimeRange(start: kCMTimeZero, duration: asset.duration) + private func prepareForReading() throws { if samplesHandler == nil { print("\(#function)[\(#line)] Caution!!! There is no samples handler") } - - self.readingRoutine = SamplesReadingRoutine(assetReader: assetReader, readerOutput: readerOutput, audioFormat: samplesReadAudioFormat, samplesHandler: samplesHandler, progress: self.progress) + + do { + self.readingRoutine = try SamplesReadingRoutine(asset: asset, + audioFormat: samplesReadAudioFormat, + samplesHandler: samplesHandler, + progress: self.progress) + } catch { + throw error + } } private func read() throws { @@ -145,20 +136,56 @@ class AudioSamplesReader: NSObject { final class SamplesReadingRoutine { - let assetReader: AVAssetReader - let readerOutput: AVAssetReaderOutput + var assetReader: AVAssetReader + var readerOutput: AVAssetReaderOutput let audioFormat: AudioFormat weak var samplesHandler: AudioSamplesHandler? - + var lastTimestamp: CMTime = kCMTimeZero + let asset : AVAsset + let progress: Progress lazy var estimatedSamplesCount: Int = { return Int(self.assetReader.asset.duration.seconds * Double(self.audioFormat.samplesRate)) }() - init(assetReader: AVAssetReader, readerOutput: AVAssetReaderOutput, audioFormat: AudioFormat, samplesHandler: AudioSamplesHandler?, progress: Progress) { - self.assetReader = assetReader - self.readerOutput = readerOutput + func restart() throws { + let cortege = try SamplesReadingRoutine.getAssetReaderAndOutput(asset: asset, audioFormat: audioFormat) + assetReader = cortege.0 + readerOutput = cortege.1 + assetReader.timeRange = CMTimeRange(start: lastTimestamp, duration: asset.duration) + try startReading() + } + + static func getAssetReaderAndOutput(asset: AVAsset, audioFormat: AudioFormat) throws -> (AVAssetReader, AVAssetReaderOutput) { + let sound : AVAssetTrack + sound = try asset.tracks(withMediaType: AVMediaTypeAudio).first! + + let assetReader: AVAssetReader + do { + assetReader = try AVAssetReader(asset: asset) + } catch let error as NSError { + throw SamplesReaderError.UnknownError(error) + } + + let settings = AudioSamplesReader.audioReadingSettings(forFormat: audioFormat) + + let readerOutput = AVAssetReaderTrackOutput(track: sound, outputSettings: settings) + + assetReader.add(readerOutput) + assetReader.timeRange = CMTimeRange(start: kCMTimeZero, duration: asset.duration) + + return (assetReader, readerOutput) + } + + init(asset: AVAsset, audioFormat: AudioFormat, samplesHandler: AudioSamplesHandler?, progress: Progress) throws { + + self.asset = asset + + let cortege = try SamplesReadingRoutine.getAssetReaderAndOutput(asset: asset, audioFormat: audioFormat) + + self.assetReader = cortege.0 + self.readerOutput = cortege.1 self.audioFormat = audioFormat self.samplesHandler = samplesHandler self.progress = progress @@ -187,6 +214,8 @@ final class SamplesReadingRoutine { try readNextSamples() } catch (_ as NoMoreSampleBuffersAvailable) { break + } catch (_ as UnknownError){ + try restart() } catch { cancelReading() throw error @@ -198,7 +227,12 @@ final class SamplesReadingRoutine { func readNextSamples() throws { guard let sampleBuffer = readerOutput.copyNextSampleBuffer() else { - throw NoMoreSampleBuffersAvailable() + + if assetReader.status == .failed, assetReader.error != nil { + throw UnknownError() + } else { + throw NoMoreSampleBuffersAvailable() + } } // Get buffer @@ -206,6 +240,11 @@ final class SamplesReadingRoutine { throw SamplesReaderError.UnknownError(nil) } + let duration = CMSampleBufferGetOutputDuration(sampleBuffer) + let presentationTimeStamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer) + + lastTimestamp = presentationTimeStamp + duration + let length = CMBlockBufferGetDataLength(buffer) // Append new data diff --git a/Source/Utility/Error.swift b/Source/Utility/Error.swift index 1a3667a..be23416 100644 --- a/Source/Utility/Error.swift +++ b/Source/Utility/Error.swift @@ -19,3 +19,4 @@ enum SamplesReaderError: Error { struct NoMoreSampleBuffersAvailable: Error {} struct NoEnoughData: Error {} +struct UnknownError: Error {} From 267bad17ba0dd689ad588d056e0c6cb424673eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A0=D1=8F=D0=B1=D0=BE=D0=B2?= Date: Mon, 12 Dec 2016 19:47:41 +0300 Subject: [PATCH 31/31] Fix for cursor position --- Source/View/PlaybackPositionView.swift | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Source/View/PlaybackPositionView.swift b/Source/View/PlaybackPositionView.swift index 3ce507b..0aaa210 100644 --- a/Source/View/PlaybackPositionView.swift +++ b/Source/View/PlaybackPositionView.swift @@ -40,15 +40,20 @@ class PlaybackPositionView: UIView { let position = (self.bounds.width - lineWidth) * relativePosition + lineWidth/2 cursor.center = CGPoint(x: position, y: center.y) - - self.setNeedsLayout() + } + + public override func layoutSubviews() { + positionCursor() } /// Value from 0 to 1 /// Setting value causes setNeedsDisplay method call /// Setting nil causes removing cursor var position: CGFloat? { - didSet { self.positionCursor() } + didSet { + self.positionCursor() + setNeedsLayout() + } } var lineColor = UIColor.white var lineWidth: CGFloat = 2.0