Browse Source

Local Files extern

master
marcoschmickler 4 years ago
parent
commit
6f476c0cb3
  1. 4
      kplayer.xcodeproj/project.pbxproj
  2. 22
      kplayer/core/LocalManager.swift
  3. 14
      kplayer/core/MediaItem.swift
  4. 2
      kplayer/detail/DetailViewController.swift
  5. 65
      kplayer/detail/EditItemView.swift
  6. 329
      kplayer/detail/VideoController.swift
  7. 24
      kplayer/master/NetworkDelegate.swift
  8. 26
      kplayer/video/BMPlayer.swift
  9. 30
      kplayer/video/KVideoPlayer.swift

4
kplayer.xcodeproj/project.pbxproj

@ -46,6 +46,7 @@
1C736A06A2AD75B8C14EEBBE /* HtmlParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C736DBB6986A8B62963FBB3 /* HtmlParser.swift */; }; 1C736A06A2AD75B8C14EEBBE /* HtmlParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C736DBB6986A8B62963FBB3 /* HtmlParser.swift */; };
1C736A5FA5BA53B2597F2ED7 /* Kirschkeks-256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C736059262A57AADE6AB761 /* Kirschkeks-256x256.png */; }; 1C736A5FA5BA53B2597F2ED7 /* Kirschkeks-256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C736059262A57AADE6AB761 /* Kirschkeks-256x256.png */; };
1C736A622876405F3EE2D043 /* EditItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7366C09381DC0052B52B69 /* EditItemView.swift */; }; 1C736A622876405F3EE2D043 /* EditItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7366C09381DC0052B52B69 /* EditItemView.swift */; };
1C736A78C1F8F41E2AEEF278 /* KVideoPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C736E2CD0C1780F4F5AE0C4 /* KVideoPlayer.swift */; };
1C736A7B6221A1D50FB3904C /* ItemType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C73631C96E6C860833052CA /* ItemType.swift */; }; 1C736A7B6221A1D50FB3904C /* ItemType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C73631C96E6C860833052CA /* ItemType.swift */; };
1C736CB96577F6A9A7BA03E8 /* BMPlayerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7364F924BD979294C3EE4A /* BMPlayerItem.swift */; }; 1C736CB96577F6A9A7BA03E8 /* BMPlayerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7364F924BD979294C3EE4A /* BMPlayerItem.swift */; };
1C736CD0E54786D3A2405E51 /* BMPlayerLayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7366D766CDE0C9872E86F5 /* BMPlayerLayerView.swift */; }; 1C736CD0E54786D3A2405E51 /* BMPlayerLayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7366D766CDE0C9872E86F5 /* BMPlayerLayerView.swift */; };
@ -137,6 +138,7 @@
1C736DBB6986A8B62963FBB3 /* HtmlParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlParser.swift; sourceTree = "<group>"; }; 1C736DBB6986A8B62963FBB3 /* HtmlParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlParser.swift; sourceTree = "<group>"; };
1C736DCCE3AA9993E15F7652 /* UIImageExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageExtension.swift; sourceTree = "<group>"; }; 1C736DCCE3AA9993E15F7652 /* UIImageExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageExtension.swift; sourceTree = "<group>"; };
1C736DFBD072763248412F74 /* BMPlayerClearityChooseButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BMPlayerClearityChooseButton.swift; sourceTree = "<group>"; }; 1C736DFBD072763248412F74 /* BMPlayerClearityChooseButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BMPlayerClearityChooseButton.swift; sourceTree = "<group>"; };
1C736E2CD0C1780F4F5AE0C4 /* KVideoPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KVideoPlayer.swift; sourceTree = "<group>"; };
1C736E51F1A03E3A1200BDB6 /* BMPlayerControlView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BMPlayerControlView.swift; sourceTree = "<group>"; }; 1C736E51F1A03E3A1200BDB6 /* BMPlayerControlView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BMPlayerControlView.swift; sourceTree = "<group>"; };
1C736EA15A11AF7D57F85824 /* ThumbnailCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThumbnailCache.swift; sourceTree = "<group>"; }; 1C736EA15A11AF7D57F85824 /* ThumbnailCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThumbnailCache.swift; sourceTree = "<group>"; };
1C736F9338CE36708244D42A /* DataLoadOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataLoadOperation.swift; sourceTree = "<group>"; }; 1C736F9338CE36708244D42A /* DataLoadOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataLoadOperation.swift; sourceTree = "<group>"; };
@ -267,6 +269,7 @@
1C7360AE55EB115762C42EB9 /* BMTimeSlider.swift */, 1C7360AE55EB115762C42EB9 /* BMTimeSlider.swift */,
1C7360D6580FB5D09C2BBCCB /* BMPlayerManager.swift */, 1C7360D6580FB5D09C2BBCCB /* BMPlayerManager.swift */,
1C73610B997EBA367C806C1B /* BMPlayerCompositionResourceDefinition.swift */, 1C73610B997EBA367C806C1B /* BMPlayerCompositionResourceDefinition.swift */,
1C736E2CD0C1780F4F5AE0C4 /* KVideoPlayer.swift */,
); );
path = video; path = video;
sourceTree = "<group>"; sourceTree = "<group>";
@ -584,6 +587,7 @@
1C736A622876405F3EE2D043 /* EditItemView.swift in Sources */, 1C736A622876405F3EE2D043 /* EditItemView.swift in Sources */,
1C73613562EB375F53A0BD03 /* ServerDownloadDelegate.swift in Sources */, 1C73613562EB375F53A0BD03 /* ServerDownloadDelegate.swift in Sources */,
1C736EC45EE7DA5F7FCE63DA /* LocalManager.swift in Sources */, 1C736EC45EE7DA5F7FCE63DA /* LocalManager.swift in Sources */,
1C736A78C1F8F41E2AEEF278 /* KVideoPlayer.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

22
kplayer/core/LocalManager.swift

@ -86,9 +86,12 @@ class LocalManager {
let json = item.toJSON() let json = item.toJSON()
do { do {
print(url)
try json.write(to: url.appendingPathExtension("json"), atomically: true, encoding: .utf8)
let input = try String(contentsOf: url)
var jsonurl = url
if url.pathExtension != "json" {
jsonurl = url.appendingPathExtension("json")
}
try json.write(to: jsonurl, atomically: true, encoding: .utf8)
let input = try String(contentsOf: jsonurl)
print(input) print(input)
} catch { } catch {
print(json) print(json)
@ -181,6 +184,7 @@ class LocalManager {
let item = try JSONDecoder().decode(MediaModel.self, from: jsonData) let item = try JSONDecoder().decode(MediaModel.self, from: jsonData)
let mediaItem = MediaItem(model: item) let mediaItem = MediaItem(model: item)
mediaItem.externalURL = fileURL.absoluteString mediaItem.externalURL = fileURL.absoluteString
mediaItem.localURL = jsonURL
mediaItem.local = true mediaItem.local = true
for i in mediaItem.children { for i in mediaItem.children {
i.externalURL = fileURL.absoluteString i.externalURL = fileURL.absoluteString
@ -253,9 +257,15 @@ class LocalManager {
} }
if path!.contains("file://") { if path!.contains("file://") {
let p = path!.substringAfter("/Documents/")
let fixed = FileHelper.getDocumentsDirectory().appendingPathComponent(p)
return fixed.absoluteString
if path!.contains("/Application") {
let p = path!.substringAfter("/Documents/")
let fixed = FileHelper.getDocumentsDirectory().appendingPathComponent(p)
return fixed.absoluteString
}
else {
let p = path!.substringAfter("/Documents")
return externalURL + p
}
} }
return path return path
} }

14
kplayer/core/MediaItem.swift

@ -5,6 +5,7 @@
import Foundation import Foundation
import UIKit import UIKit
import Combine
/** /**
Repräsentiert ein Item eines der festgelegten Typen. Repräsentiert ein Item eines der festgelegten Typen.
@ -38,8 +39,18 @@ class MediaItem: CustomDebugStringConvertible, ObservableObject {
// Nutzinhalt // Nutzinhalt
var image: UIImage? var image: UIImage?
// let didChange = PassthroughSubject<MediaItem,Never>()
@Published @Published
var time: TimeInterval = 0.0 var time: TimeInterval = 0.0
//
// {
// willSet {
// // print(newValue)
// // didChange.send(self)
// self.objectWillChange.send()
// }
// }
@Published @Published
var length: TimeInterval = 0.0 var length: TimeInterval = 0.0
@ -49,13 +60,14 @@ class MediaItem: CustomDebugStringConvertible, ObservableObject {
var thumbUrl: String? var thumbUrl: String?
var externalURL: String? var externalURL: String?
var localURL: URL?
var local = false var local = false
var external = false var external = false
var leaf = false var leaf = false
var cancelled = false var cancelled = false
var scale = 0.0
var scale = 1.0
var offset = CGPoint() var offset = CGPoint()
var size = CGSize() var size = CGSize()

2
kplayer/detail/DetailViewController.swift

@ -307,7 +307,7 @@ class DetailViewController: UIViewController, UICollectionViewDelegateFlowLayout
} }
} }
else if items.local { else if items.local {
self.delegate!.deleteLocal(selectedItem: items)
// self.delegate!.deleteLocal(selectedItem: items)
} }
})) }))

65
kplayer/detail/EditItemView.swift

@ -6,41 +6,70 @@
import Foundation import Foundation
import SwiftUI import SwiftUI
struct EditItemView : View {
struct EditItemView: View {
@ObservedObject @ObservedObject
var item : MediaItem
var item: MediaItem
var len: Double
var seek: (Double) -> Void
var capture: (MediaItem) -> Void
var body: some View { var body: some View {
Form { Form {
Section(header: Text("K Settings")) { Section(header: Text("K Settings")) {
VStack { VStack {
Text("Size")
Slider(value: $item.time, in: 0...1000)
Slider(value: $item.length, in: 0...1000)
Slider(value: Binding<Double>(
get: { item.time },
set: {
item.time = $0
seek(item.time)
}
), in: 0...len)
Text("Start \(item.time, specifier: "%.1f") Length \(item.length, specifier: "%.1f")")
Slider(value: Binding<Double>(
get: { item.length },
set: {
item.length = $0
seek(item.time + item.length)
}
), in: 1...500)
Toggle(isOn: $item.loop, label: { Toggle(isOn: $item.loop, label: {
Text("Loop") Text("Loop")
}) })
}
}
Button(action: {
}, label: {
Text("ok")
});
Button(action: {
}, label: {
Text("cancel")
})
Text("Zoom \(item.scale, specifier: "%.1f") X \(item.offset.x, specifier: "%.1f") Y \(item.offset.y, specifier: "%.1f") ")
HStack {
Button(action: {
capture(item)
item.objectWillChange.send()
}, label: {
Text("Zoom")
});
// Button(action: {
// item.scale = 1.0
// item.offset = CGPoint(x: 0,y: 0)
// item.objectWillChange.send()
// }, label: {
// Text("Reset")
// });
}
}.background(Color.clear)
}.background(Color.clear)
} }
.onAppear { .onAppear {
UITableView.appearance().backgroundColor = .clear
}
.onDisappear {
UITableView.appearance().backgroundColor = .systemBackground
} }
.frame(height: 350, alignment: .top)
//Spacer()
} }
} }
struct EditItemView_Previews: PreviewProvider { struct EditItemView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
EditItemView(item: MediaItem(name: "extern", path:"", root: "", type: ItemType.FAVROOT))
EditItemView(item: MediaItem(name: "extern", path: "", root: "", type: ItemType.FAVROOT), len: 1000, seek: { v in }, capture: { v in })
} }
} }

329
kplayer/detail/VideoController.swift

@ -36,7 +36,6 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate {
var downloadDelegate: DownloadDelegate? var downloadDelegate: DownloadDelegate?
var loopStart = 0.0 var loopStart = 0.0
var loopEnd = 0.0
var completionHandler: (() -> Void)? var completionHandler: (() -> Void)?
@ -56,11 +55,11 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate {
var aspect = 1 var aspect = 1
var loopOption = 0
var loopMode = false
var thumbnailTime: TimeInterval = 0.0 var thumbnailTime: TimeInterval = 0.0
var edit = true
var edit = false
var allowEdit = true var allowEdit = true
var index = 0 var index = 0
@ -74,7 +73,7 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate {
barbutton = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(VideoController.captureThumbnail)); barbutton = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(VideoController.captureThumbnail));
navigationItem.rightBarButtonItems = [barbutton!] navigationItem.rightBarButtonItems = [barbutton!]
backButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(VideoController.back(_:)))
backButton = UIBarButtonItem(title: "0:00", style:UIBarButtonItem.Style.plain, target: self, action: #selector(VideoController.back(_:)))
speedButton = UIBarButtonItem(title:"1.0", style:UIBarButtonItem.Style.plain, target: self, action: #selector(VideoController.speed(_:))) speedButton = UIBarButtonItem(title:"1.0", style:UIBarButtonItem.Style.plain, target: self, action: #selector(VideoController.speed(_:)))
loopButton = UIBarButtonItem(title:"1.0", style:UIBarButtonItem.Style.plain, target: self, action: #selector(VideoController.loop(_:))) loopButton = UIBarButtonItem(title:"1.0", style:UIBarButtonItem.Style.plain, target: self, action: #selector(VideoController.loop(_:)))
aspectButton = UIBarButtonItem(title:"1", style:UIBarButtonItem.Style.plain, target: self, action: #selector(VideoController.aspect(_:))) aspectButton = UIBarButtonItem(title:"1", style:UIBarButtonItem.Style.plain, target: self, action: #selector(VideoController.aspect(_:)))
@ -86,11 +85,11 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate {
view.addSubview(player) view.addSubview(player)
player.snp.makeConstraints { (make) in player.snp.makeConstraints { (make) in
// make.top.equalTo(self.view).offset(100)
// make.top.equalTo(self.view).offset(100)
make.left.right.equalTo(self.view) make.left.right.equalTo(self.view)
make.height.equalTo(self.view) make.height.equalTo(self.view)
// Note here, the aspect ratio 16:9 priority is lower than 1000 on the line, because the 4S iPhone aspect ratio is not 16:9 // Note here, the aspect ratio 16:9 priority is lower than 1000 on the line, because the 4S iPhone aspect ratio is not 16:9
// make.height.equalTo(player.snp.width).multipliedBy(9.0/16.0).priority(750)
// make.height.equalTo(player.snp.width).multipliedBy(9.0/16.0).priority(750)
} }
player.delegate = self player.delegate = self
@ -102,20 +101,41 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate {
if let c = currentItem, let url = c.playerURL { if let c = currentItem, let url = c.playerURL {
print(url) print(url)
play(url as URL) play(url as URL)
// player.playerLayer!.player!.volume = 0.0
// player.playerLayer!.player!.volume = 0.0
update() update()
} }
loopMode = detailDelegate!.settings().autoloop
updateLoop() updateLoop()
} }
func editItem() { func editItem() {
let kv = EditItemView(item: currentSnapshot!)
let currentItem = player.playerLayer?.player?.currentItem
let totalTime : Double
if let playerItem = currentItem {
totalTime = TimeInterval(playerItem.duration.value) / TimeInterval(playerItem.duration.timescale)
}
else {
totalTime = 1000
}
let kv = EditItemView(item: currentSnapshot!, len: totalTime, seek:
{ value in
print(value)
self.player.seekSmoothlyToTime(newChaseTime: value)
}, capture: { item in
item.scale = Double(self.player.zoom)
item.offset = CGPoint(x: self.player.xpos, y: self.player.ypos)
})
let pc = UIHostingController(rootView: kv) 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 = .fullScreen
// navController.modalPresentationStyle = .popover
present(navController, animated: false, completion: nil) present(navController, animated: false, completion: nil)
} }
@ -146,6 +166,8 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate {
} }
else { else {
edit = true edit = true
loopMode = false
updateLoop()
reviewButton!.tintColor = UIColor.yellow reviewButton!.tintColor = UIColor.yellow
} }
} }
@ -235,7 +257,7 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate {
file = file.appendingPathExtension("mp4") file = file.appendingPathExtension("mp4")
} }
print (file) print (file)
var dur = loopEnd - loopStart
var dur = player.loopEnd - loopStart
if (dur < 0) { if (dur < 0) {
return return
} }
@ -278,45 +300,31 @@ class VideoController: UIViewController, ItemController, BMPlayerDelegate {
} }
else { else {
if player.isPlayToTheEnd { if player.isPlayToTheEnd {
player.seek(0, completion: {[weak self] in
self!.player.play()
})
player.seekSmoothlyToTime(newChaseTime: 0)
player.isPlayToTheEnd = false player.isPlayToTheEnd = false
} }
player.play() player.play()
} }
print("play")
print("play")
} }
@objc func loop(_ sender: AnyObject) { @objc func loop(_ sender: AnyObject) {
loopOption += 1
if loopOption >= 2 {
loopOption = 0
if edit {
loopMode = false
} }
if loopOption == 1 {
let t = player.playerLayer!.player!.currentTime()
loopEnd = (Double(t.value) / Double(t.timescale)) - 2.0
else {
loopMode = !loopMode
} }
updateLoop() updateLoop()
} }
func updateLoop() { func updateLoop() {
if loopOption == 1 {
var dur = loopEnd - loopStart
if dur > 0 {
loopButton!.title = "(\(dur))"
}
else {
loopButton!.title = "cont"
}
if loopMode {
loopButton!.title = "loop"
} }
else { else {
loopButton!.title = "loop"
loopButton!.title = "cont"
} }
} }
@objc func aspect(_ sender: AnyObject) { @objc func aspect(_ sender: AnyObject) {
@ -325,9 +333,9 @@ print("play")
aspect = 1 aspect = 1
} }
switch aspect { switch aspect {
case 1:
player.aspectx = 1.0
player.aspecty = 1.0
case 1:
player.aspectx = 1.0
player.aspecty = 1.0
case 2: case 2:
player.aspectx = 0.9 player.aspectx = 0.9
player.aspecty = 1.0 player.aspecty = 1.0
@ -337,7 +345,7 @@ print("play")
default: default:
print("aspect") print("aspect")
} }
// todo player.verticalMoved(0)
// todo player.verticalMoved(0)
player.transformLayer() player.transformLayer()
aspectButton!.title = "\(aspect)" aspectButton!.title = "\(aspect)"
} }
@ -388,7 +396,7 @@ print("play")
} }
} }
let asset = BMPlayerResource(name: "video", definitions: def) let asset = BMPlayerResource(name: "video", definitions: def)
// let asset = BMPlayerResource(url: url)
// let asset = BMPlayerResource(url: url)
player.setVideo(resource: asset, definitionIndex: index) player.setVideo(resource: asset, definitionIndex: index)
player.playerLayer!.player!.automaticallyWaitsToMinimizeStalling = false player.playerLayer!.player!.automaticallyWaitsToMinimizeStalling = false
@ -400,8 +408,8 @@ print("play")
} }
func playerItemDidReachEnd(_ note: Notification) { func playerItemDidReachEnd(_ note: Notification) {
print("finish")
// Timer.scheduledTimer(timeInterval: 0.6, target: self, selector: #selector(update), userInfo: nil, repeats: false)
print("finish")
// Timer.scheduledTimer(timeInterval: 0.6, target: self, selector: #selector(update), userInfo: nil, repeats: false)
} }
@ -439,52 +447,62 @@ print("finish")
} }
@objc func thumbnailClicked(_ source: UIButton) { @objc func thumbnailClicked(_ source: UIButton) {
currentSnapshot = buttons[source]
player.seek(buttons[source]!.time)
loopStart = buttons[source]!.time
loopOption = 0
loopButton!.title = "loop"
if let currentSnapshot = buttons[source] {
gotoSnapshot(currentSnapshot: currentSnapshot)
if (edit) {
// editItem()
if (edit) {
editItem()
}
}
// moviePlayer!.currentPlaybackRate = Float(speedOptions[speedOption])
// print("goto \(buttons[source]!.time!) is \(moviePlayer!.currentPlaybackTime)")
}
private func gotoSnapshot(currentSnapshot: MediaItem) {
player.seekSmoothlyToTime(newChaseTime: currentSnapshot.time)
loopStart = currentSnapshot.time
player.loopEnd = loopStart + currentSnapshot.length
if loopMode && currentSnapshot.scale > 0 {
player.zoom = Float(currentSnapshot.scale)
player.xpos = currentSnapshot.offset.x
player.ypos = currentSnapshot.offset.y
player.transformLayer()
} }
// moviePlayer!.currentPlaybackRate = Float(speedOptions[speedOption])
// print("goto \(buttons[source]!.time!) is \(moviePlayer!.currentPlaybackTime)")
self.currentSnapshot = currentSnapshot
} }
@objc func update() { @objc func update() {
reviewButton!.title = currentItem!.name
reviewButton!.title = currentItem!.name
if currentItem!.type == ItemType.SNAPSHOT {
player.seek(currentItem!.time)
if detailDelegate!.settings().autoloop && currentItem!.loop {
loopStart = currentItem!.time
loopEnd = currentItem!.time + currentItem!.length
loopOption = 1
}
currentItem = currentItem!.parent
} else {
if !currentItem!.children.isEmpty {
player.seek(currentItem!.children[0].time)
}
else {
let duration = player.playerLayer!.playerItem!.duration
if !duration.isIndefinite {
print(duration)
player.seek(duration.seconds / 2.0)
}
if currentItem!.type == ItemType.SNAPSHOT {
player.seek(currentItem!.time)
loopStart = currentItem!.time
player.loopEnd = currentItem!.time + currentItem!.length
currentItem = currentItem!.parent
} else {
if !currentItem!.children.isEmpty {
player.seekSmoothlyToTime(newChaseTime: currentItem!.children[0].time)
}
else {
let duration = player.playerLayer!.playerItem!.duration
if !duration.isIndefinite {
print(duration)
player.seekSmoothlyToTime(newChaseTime: duration.seconds / 2.0)
} }
} }
}
navigationItem.rightBarButtonItems = [barbutton!]
navigationItem.rightBarButtonItems = [barbutton!]
for c in currentItem!.children {
addItemButton(c)
}
for c in currentItem!.children {
addItemButton(c)
}
player.play()
player.play()
} }
@ -535,38 +553,38 @@ print("finish")
@objc func swipeUp() { @objc func swipeUp() {
print("u") print("u")
print("Type: \(currentItem!.type) Count: \(currentItem!.children.count) Index: \(index) Current: \(currentItem!.index)")
print("Type: \(currentItem!.type) Count: \(currentItem!.children.count) Index: \(index) Current: \(currentItem!.index)")
if !edit && (currentItem!.children.isEmpty || !(index < currentItem!.children.count - 1)) {
print ("switch")
var newIndex = currentItem!.index + 1
if !edit && (currentItem!.children.isEmpty || !(index < currentItem!.children.count - 1)) {
print ("switch")
var newIndex = currentItem!.index + 1
if currentItem!.parent!.children.count <= newIndex {
newIndex = 0
}
if currentItem!.parent!.children.count <= newIndex {
newIndex = 0
}
currentItem = currentItem!.parent!.children[newIndex]
currentItem = currentItem!.parent!.children[newIndex]
print("'Switched Type: \(currentItem!.type) Count: \(currentItem!.children.count) Index: \(index) Current: \(currentItem!.index)")
print("'Switched Type: \(currentItem!.type) Count: \(currentItem!.children.count) Index: \(index) Current: \(currentItem!.index)")
index = 0
// player.playWithURL(currentItem!.playerURL)
Timer.scheduledTimer(timeInterval: 1.2, target: self, selector: #selector(update), userInfo: nil, repeats: false)
index = 0
// player.playWithURL(currentItem!.playerURL)
Timer.scheduledTimer(timeInterval: 1.2, target: self, selector: #selector(update), userInfo: nil, repeats: false)
return
}
return
}
if !(currentItem!.children.isEmpty) {
print ("switch internal")
if index < currentItem!.children.count - 1 {
index+=1;
} else {
index = 0;
}
let child = currentItem!.children[index]
// player.currentPlaybackTime = child.time!
// player.currentPlaybackRate = Float(speedOptions[speedOption])
if !(currentItem!.children.isEmpty) {
print ("switch internal")
if index < currentItem!.children.count - 1 {
index+=1;
} else {
index = 0;
} }
let child = currentItem!.children[index]
// player.currentPlaybackTime = child.time!
// player.currentPlaybackRate = Float(speedOptions[speedOption])
}
} }
@ -585,28 +603,28 @@ print("finish")
@objc func swipeDown() { @objc func swipeDown() {
print("d") print("d")
if !edit {
var newIndex = currentItem!.index - 1
if !edit {
var newIndex = currentItem!.index - 1
if newIndex < 0 {
newIndex = 0
}
if newIndex < 0 {
newIndex = 0
}
currentItem = currentItem!.parent!.children[newIndex]
index = 0;
currentItem = currentItem!.parent!.children[newIndex]
index = 0;
// player.contentURL = currentItem!.playerURL
player.play()
Timer.scheduledTimer(timeInterval: 1.2, target: self, selector: #selector(update), userInfo: nil, repeats: false)
// player.contentURL = currentItem!.playerURL
player.play()
Timer.scheduledTimer(timeInterval: 1.2, target: self, selector: #selector(update), userInfo: nil, repeats: false)
return
}
// player.currentPlaybackTime = player.currentPlaybackTime + 10.0
Timer.scheduledTimer(timeInterval: 0.9,
target: self,
selector: #selector(resumePlay),
userInfo: nil,
repeats: false)
return
}
// player.currentPlaybackTime = player.currentPlaybackTime + 10.0
Timer.scheduledTimer(timeInterval: 0.9,
target: self,
selector: #selector(resumePlay),
userInfo: nil,
repeats: false)
} }
@ -615,11 +633,11 @@ print("finish")
print("l") print("l")
// player.currentPlaybackRate = Float(0.0) // player.currentPlaybackRate = Float(0.0)
// player.currentPlaybackTime = player.currentPlaybackTime + 30.0 // player.currentPlaybackTime = player.currentPlaybackTime + 30.0
Timer.scheduledTimer(timeInterval: 0.9,
target: self,
selector: #selector(resumePlay),
userInfo: nil,
repeats: false)
Timer.scheduledTimer(timeInterval: 0.9,
target: self,
selector: #selector(resumePlay),
userInfo: nil,
repeats: false)
} }
@ -645,7 +663,7 @@ print("finish")
} catch let error { } catch let error {
print("*** Error generating thumbnail: \(error.localizedDescription)") print("*** Error generating thumbnail: \(error.localizedDescription)")
} }
// thumbnailTime = player.currentPlaybackTime
// thumbnailTime = player.currentPlaybackTime
print("tap \(thumbnailTime)") print("tap \(thumbnailTime)")
// moviePlayer!.requestThumbnailImages(atTimes: [thumbnailTime], // moviePlayer!.requestThumbnailImages(atTimes: [thumbnailTime],
// timeOption: MPMovieTimeOption.exact); // timeOption: MPMovieTimeOption.exact);
@ -667,6 +685,61 @@ print("finish")
addItemButton(newItem) addItemButton(newItem)
} }
func moveUp() {
let t = Date().timeIntervalSince1970
if lastMove + 2 > t {
return
}
lastMove = t
if let c = currentItem?.children {
if !c.isEmpty{
if let s = currentSnapshot {
if var i = c.firstIndex { x in x===s } {
print(i)
i+=1
if i >= c.count {
i = 0
}
gotoSnapshot(currentSnapshot: c[i])
}
}
else {
gotoSnapshot(currentSnapshot: c[0])
}
}
}
}
var lastMove = 0.0
func moveDown() {
let t = Date().timeIntervalSince1970
if lastMove + 2 > t {
return
}
lastMove = t
if let c = currentItem?.children {
if !c.isEmpty{
if let s = currentSnapshot {
if var i = c.firstIndex { x in x===s } {
print(i)
i-=1
if i < 0 {
i = c.count-1
}
gotoSnapshot(currentSnapshot: c[i])
}
}
else {
gotoSnapshot(currentSnapshot: c[0])
}
}
}
}
func bmPlayer(player: BMPlayer) { func bmPlayer(player: BMPlayer) {
let speed = Float(speedOptions[speedOption]) let speed = Float(speedOptions[speedOption])
if let pl = player.playerLayer!.player { if let pl = player.playerLayer!.player {
@ -680,16 +753,20 @@ print("finish")
} }
func bmPlayer(player: BMPlayer, loadedTimeDidChange loadedDuration: TimeInterval, totalDuration: TimeInterval) { func bmPlayer(player: BMPlayer, loadedTimeDidChange loadedDuration: TimeInterval, totalDuration: TimeInterval) {
// print("load")
// print("load")
} }
func bmPlayer(player: BMPlayer, playTimeDidChange currentTime: TimeInterval, totalTime: TimeInterval) { func bmPlayer(player: BMPlayer, playTimeDidChange currentTime: TimeInterval, totalTime: TimeInterval) {
if loopOption == 1 {
if currentTime > loopEnd {
player.seek(loopStart)
if loopMode {
if currentTime > player.loopEnd && loopStart < player.loopEnd {
player.chaseTime = CMTime.zero
player.seekSmoothlyToTime(newChaseTime: loopStart)
} }
} }
// print("Time")
if let b = backButton {
b.title = BMPlayer.formatSecondsToString(currentTime)
}
} }
func bmPlayer(player: BMPlayer, playerIsPlaying playing: Bool) { func bmPlayer(player: BMPlayer, playerIsPlaying playing: Bool) {

24
kplayer/master/NetworkDelegate.swift

@ -81,13 +81,25 @@ class NetworkDelegate: MasterDelegate, DetailDelegate {
} }
func deleteThumb(selectedItem c: MediaItem) { func deleteThumb(selectedItem c: MediaItem) {
let t = c.time
let ms = Int(t * 1000)
let p = c.snapshotDirPathForVideo + "\(ms).jpg"
let pt = c.snapshotDirPathForVideo + "\(ms)_thumb.jpg"
if c.local {
if let url = c.parent?.localURL {
do {
try FileManager.default.removeItem(atPath: c.thumbUrl!)
} catch {
print(c.thumbUrl)
}
LocalManager.sharedInstance.saveFavDir(url: url, item: c.parent!)
}
}
else {
let t = c.time
let ms = Int(t * 1000)
let p = c.snapshotDirPathForVideo + "\(ms).jpg"
let pt = c.snapshotDirPathForVideo + "\(ms)_thumb.jpg"
NetworkManager.sharedInstance.deleteThumb(p)
NetworkManager.sharedInstance.deleteThumb(pt)
NetworkManager.sharedInstance.deleteThumb(p)
NetworkManager.sharedInstance.deleteThumb(pt)
}
} }
func saveItem(selectedItem: MediaItem) { func saveItem(selectedItem: MediaItem) {

26
kplayer/video/BMPlayer.swift

@ -18,6 +18,8 @@ public protocol BMPlayerDelegate : class {
func bmPlayer(player: BMPlayer, playTimeDidChange currentTime : TimeInterval, totalTime: TimeInterval) func bmPlayer(player: BMPlayer, playTimeDidChange currentTime : TimeInterval, totalTime: TimeInterval)
func bmPlayer(player: BMPlayer, playerIsPlaying playing: Bool) func bmPlayer(player: BMPlayer, playerIsPlaying playing: Bool)
func bmPlayer(player: BMPlayer, playerOrientChanged isFullscreen: Bool) func bmPlayer(player: BMPlayer, playerOrientChanged isFullscreen: Bool)
func moveUp()
func moveDown()
} }
/** /**
@ -37,6 +39,7 @@ open class BMPlayer: UIView {
open var aspecty = Float(1.0) open var aspecty = Float(1.0)
var xpos = 0.0 var xpos = 0.0
var ypos = 0.0 var ypos = 0.0
var loopEnd = 0.0
open var pinchGesture: UIPinchGestureRecognizer! open var pinchGesture: UIPinchGestureRecognizer!
open var moveGesture: UIPanGestureRecognizer! open var moveGesture: UIPanGestureRecognizer!
@ -74,6 +77,12 @@ open class BMPlayer: UIView {
if gestureRecognizer.state == .began || gestureRecognizer.state == .changed { if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
zoom *= Float(gestureRecognizer.scale) zoom *= Float(gestureRecognizer.scale)
if zoom < 0.1 {
zoom = 1.0
xpos = 0
ypos = 0
}
gestureRecognizer.scale = 1.0 gestureRecognizer.scale = 1.0
transformLayer() transformLayer()
@ -259,6 +268,7 @@ open class BMPlayer: UIView {
- parameter to: target time - parameter to: target time
*/ */
open func seek(_ to:TimeInterval, completion: (()->Void)? = nil) { open func seek(_ to:TimeInterval, completion: (()->Void)? = nil) {
chaseTime = CMTime(value: Int64(to * 10000), timescale: CMTimeScale(10000))
playerLayer?.seek(to: to, completion: completion) playerLayer?.seek(to: to, completion: completion)
} }
@ -306,7 +316,11 @@ open class BMPlayer: UIView {
} }
// https://gist.github.com/shaps80/ac16b906938ad256e1f47b52b4809512 // https://gist.github.com/shaps80/ac16b906938ad256e1f47b52b4809512
private func seekSmoothlyToTime(newChaseTime: CMTime) {
public func seekSmoothlyToTime(newChaseTime: Double) {
seekSmoothlyToTime(newChaseTime: CMTime(value: Int64(newChaseTime * 10000), timescale: CMTimeScale(10000)))
}
public func seekSmoothlyToTime(newChaseTime: CMTime) {
if CMTimeCompare(newChaseTime, chaseTime) != 0 { if CMTimeCompare(newChaseTime, chaseTime) != 0 {
chaseTime = newChaseTime chaseTime = newChaseTime
@ -425,6 +439,10 @@ open class BMPlayer: UIView {
print(skipAmount) print(skipAmount)
if (skipAmount > 1500) { if (skipAmount > 1500) {
self.sumTime += TimeInterval(30) self.sumTime += TimeInterval(30)
if sumTime > loopEnd {
loopEnd = 1000000;
}
} else if skipAmount > 0 { } else if skipAmount > 0 {
self.sumTime += TimeInterval(10) self.sumTime += TimeInterval(10)
} else if skipAmount > -1500 { } else if skipAmount > -1500 {
@ -469,6 +487,12 @@ open class BMPlayer: UIView {
open func verticalMoved(_ value: CGFloat) { open func verticalMoved(_ value: CGFloat) {
print(value) print(value)
if (value < -100) { if (value < -100) {
delegate?.moveDown()
// controlView(controlView: controlView, didChooseDefinition: currentDefinition+1);
}
if (value > 100) {
delegate?.moveUp()
// controlView(controlView: controlView, didChooseDefinition: currentDefinition+1); // controlView(controlView: controlView, didChooseDefinition: currentDefinition+1);
} }

30
kplayer/video/KVideoPlayer.swift

@ -0,0 +1,30 @@
//
// Created by Marco Schmickler on 14.11.21.
// Copyright (c) 2021 Marco Schmickler. All rights reserved.
//
import SwiftUI
import AVKit
struct KVideoPlayer: View {
private let player = AVPlayer(url: URL(string: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")!)
var body: some View {
VideoPlayer(player: player)
.onAppear() {
// Start the player going, otherwise controls don't appear
player.play()
}
.onDisappear() {
// Stop the player when the view disappears
player.pause()
}
}
}
struct KVideoPlayer_Previews: PreviewProvider {
static var previews: some View {
KVideoPlayer()
}
}
Loading…
Cancel
Save