diff --git a/kplayer/core/KSettings.swift b/kplayer/core/KSettings.swift index 2f32d9d..95a1054 100644 --- a/kplayer/core/KSettings.swift +++ b/kplayer/core/KSettings.swift @@ -12,6 +12,9 @@ class KSettings: ObservableObject { @Published var autoloop = false + @Published + var edit = false + convenience init(model: KSettingsModel) { self.init() scale = model.scale diff --git a/kplayer/detail/EditItemView.swift b/kplayer/detail/EditItemView.swift index faeea4f..214d65a 100644 --- a/kplayer/detail/EditItemView.swift +++ b/kplayer/detail/EditItemView.swift @@ -10,6 +10,7 @@ protocol EditItemDelegate { func captureZoom() func setStart() func setEnd() + func cancelEdit() func seek(_ : Double) } @@ -17,6 +18,9 @@ struct EditItemView: View { @ObservedObject var item: MediaItem + @State + var scrubber = 0.0 + var len: Double var delegate: EditItemDelegate @@ -27,32 +31,43 @@ struct EditItemView: View { VStack() { HStack() { Slider(value: Binding( - get: { item.time }, + get: { scrubber }, set: { - item.time = $0 - delegate.seek(item.time) + scrubber = $0 + delegate.seek($0) + print ($0) } - ), in: 0...len) - Button(action: delegate.setStart, label: { - Text("Start") - }).buttonStyle(BorderlessButtonStyle()); + ), in: item.time...(item.time + item.length)) + } - Text("Start \(item.time, specifier: "%.1f") Length \(item.length, specifier: "%.1f")") + Text("Start \(EditItemView.formatSecondsToString(item.time)) End \(EditItemView.formatSecondsToString(item.time + item.length)) Length \(item.length, specifier: "%.1f")") HStack { - Slider(value: Binding( + Stepper(value: Binding( + get: { item.time }, + set: { s in + item.time = s + delegate.seek(item.time) + }), in: 0...len){ + Button(action: delegate.setStart, label: { + Text("Start") + }).buttonStyle(BorderlessButtonStyle()); + } + Stepper(value:Binding( get: { item.length }, - set: { - item.length = $0 + set: { l in + item.length = l delegate.seek(item.time + item.length) } - ), in: 1...500) + ), in: 1...500){ + Text("Len") + } Button(action: delegate.setEnd, label: { Text("End") }).buttonStyle(BorderlessButtonStyle()); } - Toggle(isOn: $item.loop, label: { - Text("Loop") - }) +// Toggle(isOn: $item.loop, label: { +// Text("Loop") +// }) Text("Zoom \(item.scale, specifier: "%.1f") X \(item.offset.x, specifier: "%.1f") Y \(item.offset.y, specifier: "%.1f") ") HStack { Button(action: delegate.captureZoom, label: { @@ -65,6 +80,11 @@ struct EditItemView: View { }, label: { Text("Reset") }).buttonStyle(BorderlessButtonStyle()); + Button(action: { + delegate.cancelEdit() + }, label: { + Text("cancel") + }).buttonStyle(BorderlessButtonStyle()); } }.background(Color.clear) }.background(Color.clear) @@ -78,6 +98,15 @@ struct EditItemView: View { .frame(height: 350, alignment: .top) //Spacer() } + + static func formatSecondsToString(_ seconds: TimeInterval) -> String { + if seconds.isNaN { + return "00:00" + } + let min = Int(seconds / 60) + let sec = seconds.truncatingRemainder(dividingBy: 60) + return String(format: "%02d:%.1f", min, sec) + } } struct EditItemView_Previews: PreviewProvider { diff --git a/kplayer/detail/VideoController.swift b/kplayer/detail/VideoController.swift index 0cfc039..bb5e512 100644 --- a/kplayer/detail/VideoController.swift +++ b/kplayer/detail/VideoController.swift @@ -50,8 +50,8 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate, EditI var backButton: UIBarButtonItem? var reviewButton: UIBarButtonItem? - let speedOptions = [ 0.25, 1 ] - var speedOption = 1 + let speedOptions = [ 0.25, 0.5, 1, 2 ] + var speedOption = 2 var aspect = 1 @@ -67,6 +67,9 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate, EditI var urls : [URL]? + var kv : EditItemView? + var hc : UIHostingController? + override func viewDidLoad() { super.viewDidLoad() @@ -82,6 +85,9 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate, EditI reviewButton = UIBarButtonItem(title:"Edit ", style:UIBarButtonItem.Style.plain, target: self, action: #selector(VideoController.doEdit(_:))) navigationItem.leftBarButtonItems = [backButton!, speedButton!, playButton!, loopButton!, aspectButton!, favButton!, reviewButton!] +//MediaItem(name: "extern", path: "", root: "", type: ItemType.FAVROOT) + + // pc.view.isHidden = true view.addSubview(player) player.snp.makeConstraints { (make) in @@ -106,10 +112,15 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate, EditI update() } loopMode = detailDelegate!.settings().autoloop + if detailDelegate!.settings().edit { + doEdit(self) + } updateLoop() } func editItem() { + cancelEdit() + let currentItem = player.playerLayer?.player?.currentItem let totalTime : Double @@ -124,14 +135,28 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate, EditI setEnd() } - let kv = EditItemView(item: currentSnapshot!, len: totalTime, delegate: self) + kv = EditItemView(item: currentSnapshot!, len: totalTime, delegate: self) + hc = UIHostingController(rootView: kv!) + addChild(hc!) + + view.addSubview(hc!.view) + + hc!.view.backgroundColor = .clear + hc!.view.snp.makeConstraints { (make) in + make.width.equalTo(400) + make.height.equalTo(300) + make.right.equalToSuperview() + make.top.equalToSuperview() + } + // player.controlView.topWrapperView.addSubview(hc!.view) + + // player.controlView.setNeedsLayout() + // player.controlView.layoutIfNeeded() - let pc = UIHostingController(rootView: kv) - pc.view.backgroundColor = .clear - let navController = UINavigationController(rootViewController: pc) // Creating a navigation controller with pc at the root of the navigation stack. + // let navController = UINavigationController(rootViewController: pc) // Creating a navigation controller with pc at the root of the navigation stack. // navController.modalPresentationStyle = .popover - present(navController, animated: false, completion: nil) + // present(navController, animated: false, completion: nil) } @@ -167,6 +192,16 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate, EditI } } + func cancelEdit() { + if hc == nil { + return + } + + hc!.view.removeFromSuperview() + kv = nil + hc = nil + } + func seek(_ value: Double) { self.player.seekSmoothlyToTime(newChaseTime: value) } @@ -694,6 +729,10 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate, EditI } func moveUp() { + if !loopMode { + return + } + let t = Date().timeIntervalSince1970 if lastMove + 2 > t { return @@ -722,6 +761,10 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate, EditI var lastMove = 0.0 func moveDown() { + if !loopMode { + return + } + let t = Date().timeIntervalSince1970 if lastMove + 2 > t { return diff --git a/kplayer/master/KSettingsView.swift b/kplayer/master/KSettingsView.swift index 9455bdd..79d4b39 100644 --- a/kplayer/master/KSettingsView.swift +++ b/kplayer/master/KSettingsView.swift @@ -21,6 +21,9 @@ struct KSettingsView: View { Toggle(isOn: $kSettings.autoloop, label: { Text("Autoloop") }) + Toggle(isOn: $kSettings.edit, label: { + Text("Edit") + }) } } Button(action: { diff --git a/kplayer/video/BMPlayer.swift b/kplayer/video/BMPlayer.swift index e89e1b0..5432404 100644 --- a/kplayer/video/BMPlayer.swift +++ b/kplayer/video/BMPlayer.swift @@ -33,7 +33,7 @@ enum BMPanDirection: Int { case vertical = 1 } -open class BMPlayer: UIView { +open class BMPlayer: UIView, UIGestureRecognizerDelegate { open var zoom = Float(1.0) open var aspectx = Float(1.0) open var aspecty = Float(1.0) @@ -131,7 +131,7 @@ open class BMPlayer: UIView { fileprivate var currentDefinition = 0 - fileprivate var controlView: BMPlayerControlView! + var controlView: BMPlayerControlView! fileprivate var customControlView: BMPlayerControlView? @@ -354,6 +354,14 @@ open class BMPlayer: UIView { } } + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { + if touch.view?.isDescendant(of: controlView.topWrapperView) == true { + return true + } + else { + return true + } + } // MARK: - Action Response @objc open func panDirection(_ pan: UIPanGestureRecognizer) { @@ -374,7 +382,7 @@ open class BMPlayer: UIView { let x = abs(velocityPoint.x) let y = abs(velocityPoint.y) - if (locationPoint.y < self.bounds.size.height * 1 / 8) { + if (locationPoint.y < self.bounds.size.height * 1 / 7) { self.isSkip = (zoom <= 1.0) isScrub = false @@ -441,18 +449,27 @@ open class BMPlayer: UIView { if isSkip && !isScrub { print(skipAmount) - if (skipAmount > 1500) { - self.sumTime += TimeInterval(30) - - if sumTime > loopEnd { - loopEnd = 1000000; + if (locationPoint.y < self.bounds.size.height * 1 / 8) { + if skipAmount > 0 { + self.sumTime += TimeInterval(5) + } else if skipAmount < -0 { + self.sumTime -= TimeInterval(5) + } + } + else { + if (skipAmount > 1500) { + self.sumTime += TimeInterval(30) + + if sumTime > loopEnd { + loopEnd = 1000000; + } + } else if skipAmount > 0 { + self.sumTime += TimeInterval(10) + } else if skipAmount > -1500 { + self.sumTime -= TimeInterval(10) + } else { + self.sumTime -= TimeInterval(30) } - } else if skipAmount > 0 { - self.sumTime += TimeInterval(10) - } else if skipAmount > -1500 { - self.sumTime -= TimeInterval(10) - } else { - self.sumTime -= TimeInterval(30) } controlView.controlViewAnimation(isShow: true) @@ -593,6 +610,7 @@ print(value) } panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panDirection(_:))) + panGesture.delegate = self // panGesture.minimumNumberOfTouches = 1 // panGesture.maximumNumberOfTouches = 1 self.addGestureRecognizer(panGesture) diff --git a/kplayer/video/BMPlayerControlView.swift b/kplayer/video/BMPlayerControlView.swift index e402117..6eb7e7c 100644 --- a/kplayer/video/BMPlayerControlView.swift +++ b/kplayer/video/BMPlayerControlView.swift @@ -523,19 +523,6 @@ open class BMPlayerControlView: UIView { // Top views topMaskView.addSubview(topWrapperView) - topWrapperView.addSubview(backButton) - topWrapperView.addSubview(titleLabel) - topWrapperView.addSubview(chooseDefinitionView) - - backButton.tag = BMPlayerControlView.ButtonType.back.rawValue - backButton.setImage(BMImageResourcePath("Pod_Asset_BMPlayer_back"), for: .normal) - backButton.addTarget(self, action: #selector(onButtonPressed(_:)), for: .touchUpInside) - - titleLabel.textColor = UIColor.white - titleLabel.text = "" - titleLabel.font = UIFont.systemFont(ofSize: 16) - - chooseDefinitionView.clipsToBounds = true // Bottom views bottomMaskView.addSubview(bottomWrapperView) @@ -665,23 +652,23 @@ open class BMPlayerControlView: UIView { } // Top views - backButton.snp.makeConstraints { (make) in - make.width.height.equalTo(50) - make.left.bottom.equalToSuperview() - } - - titleLabel.snp.makeConstraints { [unowned self](make) in - make.left.equalTo(self.backButton.snp.right) - make.centerY.equalTo(self.backButton) - } - - chooseDefinitionView.snp.makeConstraints { [unowned self](make) in - make.right.equalToSuperview().offset(-20) - make.top.equalTo(self.titleLabel.snp.top).offset(-4) - make.width.equalTo(60) - make.height.equalTo(30) - } - +// backButton.snp.makeConstraints { (make) in +// make.width.height.equalTo(50) +// make.left.bottom.equalToSuperview() +// } +// +// titleLabel.snp.makeConstraints { [unowned self](make) in +// make.left.equalTo(self.backButton.snp.right) +// make.centerY.equalTo(self.backButton) +// } +// +// chooseDefinitionView.snp.makeConstraints { [unowned self](make) in +// make.right.equalToSuperview().offset(-20) +// make.top.equalTo(self.titleLabel.snp.top).offset(-4) +// make.width.equalTo(60) +// make.height.equalTo(30) +// } +// // Bottom views playButton.snp.makeConstraints { (make) in make.width.equalTo(50) diff --git a/kplayer/video/BMPlayerManager.swift b/kplayer/video/BMPlayerManager.swift index 9d31aba..03fa08c 100644 --- a/kplayer/video/BMPlayerManager.swift +++ b/kplayer/video/BMPlayerManager.swift @@ -30,9 +30,9 @@ open class BMPlayerManager { /// should auto play open var shouldAutoPlay = true - open var topBarShowInCase = BMPlayerTopBarShowCase.none + open var topBarShowInCase = BMPlayerTopBarShowCase.always - open var animateDelayTimeInterval = TimeInterval(5) + open var animateDelayTimeInterval = TimeInterval(100) /// should show log open var allowLog = false