Browse Source

more

master
marcoschmickler 4 years ago
parent
commit
a707547ca9
  1. 4
      kplayer.xcodeproj/project.pbxproj
  2. 23
      kplayer/video/KToggleButton.swift
  3. 202
      kplayer/video/SVideoPlayer.swift

4
kplayer.xcodeproj/project.pbxproj

@ -21,6 +21,7 @@
1C73646F87B495A47D7943C7 /* NetData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7369EC16B19B32B515169E /* NetData.swift */; };
1C736503B656C999E5E12081 /* NetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7365B06FA66294E99AC2D3 /* NetworkManager.swift */; };
1C73654C9EA6D255CFC039C5 /* NetworkHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C73620D01687FB4F1811C5C /* NetworkHelper.swift */; };
1C736559059B6FBA1C661191 /* KToggleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C73661C3F9F4E53645551AD /* KToggleButton.swift */; };
1C7365885FAF292F2221ED44 /* PhotoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C73673DC671535E3A049F54 /* PhotoController.swift */; };
1C7365C59F72C29EA41C8717 /* SVideoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C736EEC570C71AAC50F2E95 /* SVideoModel.swift */; };
1C7365CE76693E7772585CA8 /* SVideoPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C73621E431C9BEC1440B936 /* SVideoPlayer.swift */; };
@ -113,6 +114,7 @@
1C736595533B56039C417E0D /* ServerDownloadDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServerDownloadDelegate.swift; sourceTree = "<group>"; };
1C73659CC9B523B957E58DC6 /* LocalManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalManager.swift; sourceTree = "<group>"; };
1C7365B06FA66294E99AC2D3 /* NetworkManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkManager.swift; sourceTree = "<group>"; };
1C73661C3F9F4E53645551AD /* KToggleButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KToggleButton.swift; sourceTree = "<group>"; };
1C736677D4EF2437358B2387 /* Utility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utility.swift; sourceTree = "<group>"; };
1C7366C09381DC0052B52B69 /* EditItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditItemView.swift; sourceTree = "<group>"; };
1C73673DC671535E3A049F54 /* PhotoController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoController.swift; sourceTree = "<group>"; };
@ -281,6 +283,7 @@
1C736EEC570C71AAC50F2E95 /* SVideoModel.swift */,
1C73621E431C9BEC1440B936 /* SVideoPlayer.swift */,
1C73675F8DDFA82DEADB542E /* VideoPlayerView.swift */,
1C73661C3F9F4E53645551AD /* KToggleButton.swift */,
);
path = video;
sourceTree = "<group>";
@ -592,6 +595,7 @@
1C7363C2E744C2318879127D /* FlexibleView.swift in Sources */,
1C736C8DAD6C2FBB9A2EA625 /* SearchItemView.swift in Sources */,
1C736690D123BD4B24874394 /* pathfinder.scpt in Sources */,
1C736559059B6FBA1C661191 /* KToggleButton.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

23
kplayer/video/KToggleButton.swift

@ -0,0 +1,23 @@
//
// Created by Marco Schmickler on 03.04.22.
// Copyright (c) 2022 Marco Schmickler. All rights reserved.
//
import Foundation
import SwiftUI
struct KToggleButton : View {
let text : String
@Binding var binding: Bool
var body: some View {
Button(action: {
binding.toggle()
}, label: {
Text(text)
})
.foregroundColor(binding ? Color.yellow : Color.blue).buttonStyle(BorderlessButtonStyle())
}
}

202
kplayer/video/SVideoPlayer.swift

@ -11,7 +11,7 @@ import CoreMotion
struct SVideoPlayer: View, EditItemDelegate {
// url: URL(string: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")!
var player = AVQueuePlayer(items: [AVPlayerItem]())
var playerLooper : AVPlayerLooper
var playerLooper: AVPlayerLooper
var completionHandler: ((Bool) -> Void)?
let motionManager = CMMotionManager()
@ -25,10 +25,12 @@ struct SVideoPlayer: View, EditItemDelegate {
@State var confirmationShown = false
@State var seekSmoothly = false
@State var upsidedown = false
@State var more = false
@State var tilt = false
@State var smoothTime = -1.0
@State var smoothSeekTime = -1.0
@State var timeCounter = 0
@State var lastScale = 1.25
@State var xoffs = 0.0
@State var rotazero = -1000.0
@ -38,12 +40,12 @@ struct SVideoPlayer: View, EditItemDelegate {
.makeConnectable()
.autoconnect()
let steps : [Float] = [0.25, 0.5, 1.0, 2.0 ]
let steps: [Float] = [0.25, 0.5, 1.0, 2.0]
init(completionHandler: ((Bool) -> ())?, model: SVideoModel) {
self.completionHandler = completionHandler
self.model = model
self.playerLooper = AVPlayerLooper(player: player , templateItem: model.currentPlayerItem())
self.playerLooper = AVPlayerLooper(player: player, templateItem: model.currentPlayerItem())
}
func cleanup() {
@ -68,62 +70,21 @@ struct SVideoPlayer: View, EditItemDelegate {
Text("cancel")
})
.buttonStyle(BorderlessButtonStyle())
Button(action: {
model.loop.toggle()
}, label: {
Text("loop")
})
.foregroundColor(model.loop ? Color.yellow : Color.blue).buttonStyle(BorderlessButtonStyle())
Button(action: {
model.zoomed.toggle()
}, label: {
Text("zoom")
})
.foregroundColor(model.zoomed ? Color.yellow : Color.blue).buttonStyle(BorderlessButtonStyle())
Button(action: {
upsidedown.toggle()
}, label: {
Text("flip")
}).foregroundColor(upsidedown ? Color.yellow : Color.blue).buttonStyle(BorderlessButtonStyle())
Button(action: {
tilt.toggle()
if tilt {
motionManager.startDeviceMotionUpdates(using: .xMagneticNorthZVertical)
}
else {
motionManager.stopDeviceMotionUpdates()
}
}, label: {
Text("tilt")
}).foregroundColor(tilt ? Color.yellow : Color.blue).buttonStyle(BorderlessButtonStyle())
KToggleButton(text: "more", binding: $more)
Button(action: {
model.favorite.toggle()
}, label: {
Image(systemName: "heart.fill")
})
.foregroundColor(model.favorite ? Color.yellow : Color.blue).buttonStyle(BorderlessButtonStyle())
}
Button(action: {
for s in steps {
if model.speed < s {
model.speed = s
break
}
else {
if s == 2.0 {
model.speed = steps[0]
}
}
}
player.rate = model.speed
}, label: {
Text("\(model.speed, specifier: "%.2f")")
}).buttonStyle(BorderlessButtonStyle())
Button(action: { confirmationShown = true }, label: {
Text(savetext)
}).buttonStyle(BorderlessButtonStyle())
})
.buttonStyle(BorderlessButtonStyle())
.confirmationDialog("Save to folder", isPresented: $confirmationShown) {
Button("1") {
save(currentSnapshot: model.currentSnapshot, name: "1")
@ -135,7 +96,8 @@ struct SVideoPlayer: View, EditItemDelegate {
save(currentSnapshot: model.currentSnapshot, name: "3")
}
Button("cancel", role: .cancel) {}
Button("cancel", role: .cancel) {
}
}
@ -158,13 +120,17 @@ struct SVideoPlayer: View, EditItemDelegate {
Button(action: { model.edit.toggle() }, label: {
Text("edit")
}).buttonStyle(BorderlessButtonStyle());
})
.buttonStyle(BorderlessButtonStyle());
if !model.baseItem.compilation {
Button(action: doSnapshot, label: {
Text("snap")
}).buttonStyle(BorderlessButtonStyle());
})
.buttonStyle(BorderlessButtonStyle());
}
}
.frame(height: 50)
}
}.frame(height: 50)
GeometryReader { geometry in
VStack {
@ -172,7 +138,28 @@ struct SVideoPlayer: View, EditItemDelegate {
player: player)
.scaleEffect(model.scale)
.rotation3DEffect(.degrees(upsidedown ? 180 : 0), axis: (x: 1, y: 0, z: 0))
.offset(model.dragOffset).offset(x: xoffs, y:0)
.offset(model.dragOffset).offset(x: xoffs, y: 0)
// .onTapGesture(count: 2) {
// print("Double tapped!")
// if model.paused {
// player.play()
// }
// else {
// player.pause()
// }
// model.paused = !model.paused
// }
.onTapGesture(count: 2) {
print("3 tapped!")
if model.scale == 1 {
model.scale = lastScale
} else {
lastScale = model.scale
model.scale = 1
model.dragOffset = CGSize.zero
}
}
.gesture(
DragGesture()
.onChanged { gesture in
@ -203,15 +190,76 @@ struct SVideoPlayer: View, EditItemDelegate {
if model.edit && model.videoDuration != Double.nan && model.videoDuration > 0.0 {
v.overlay(EditItemView(item: model.currentSnapshot, len: model.videoDuration, delegate: self)
.frame(width: 400, alignment: .top).offset(x: 0, y: -50), alignment: .topTrailing)
} else {
if more {
v.overlay(VStack {
Button(action: {
tilt.toggle()
if tilt {
motionManager.startDeviceMotionUpdates(using: .xMagneticNorthZVertical)
} else {
motionManager.stopDeviceMotionUpdates()
}
}, label: {
Text("tilt")
})
.frame(height: 30)
.foregroundColor(tilt ? Color.yellow : Color.blue).buttonStyle(BorderlessButtonStyle())
KToggleButton(text: "zoom", binding: $model.zoomed).frame(height: 30)
KToggleButton(text: "loop", binding: $model.loop).frame(height: 30)
KToggleButton(text: "flip", binding: $upsidedown).frame(height: 30)
Button(action: {
for s in steps {
if model.speed < s {
model.speed = s
break
} else {
if s == 2.0 {
model.speed = steps[0]
}
}
}
player.rate = model.speed
}, label: {
Text("\(model.speed, specifier: "%.2f")")
})
.frame(height: 30)
.buttonStyle(BorderlessButtonStyle())
Button(action: {
if model.paused {
player.play()
}
else {
player.pause()
}
model.paused = !model.paused
}, label: {
Text("pause")
})
.frame(height: 30)
.foregroundColor(model.paused ? Color.yellow : Color.blue).buttonStyle(BorderlessButtonStyle())
}
.frame(width: 50, alignment: .top).offset(x: 0, y: 0), alignment: .topLeading)
} else {
v
}
}
VideoPlayerControlsView(model: model,
let controlsView = VideoPlayerControlsView(model: model,
player: player)
}.onAppear {
if model.scale <= 1.0 {
controlsView
} else {
controlsView.hidden()
}
}
.onAppear {
model.proxy = geometry
print ("geo \(geometry.size.height)");
print("geo \(geometry.size.height)");
}
.clipped()
}
@ -252,8 +300,8 @@ struct SVideoPlayer: View, EditItemDelegate {
// print(xoffs)
}
// print(Int(rotation * 100.0) )
}}
else {
}
} else {
xoffs = 0.0
rotazero = -1000
}
@ -288,6 +336,7 @@ struct SVideoPlayer: View, EditItemDelegate {
.onReceive(orientationChanged) { _ in
self.orientation = UIDevice.current.orientation
}
}
func doSnapshot() {
@ -325,9 +374,8 @@ struct SVideoPlayer: View, EditItemDelegate {
if timeCounter == 0 {
if let i = model.allItems.index(where: { m in m === model.currentSnapshot }) {
if i + 1 < model.allItems.count {
gotoSnapshot(model.allItems[i+1])
}
else {
gotoSnapshot(model.allItems[i + 1])
} else {
gotoSnapshot(model.allItems[0])
}
timeCounter = 15
@ -352,8 +400,7 @@ struct SVideoPlayer: View, EditItemDelegate {
} else {
return true
}
}
else {
} else {
return true
}
}
@ -370,9 +417,9 @@ struct SVideoPlayer: View, EditItemDelegate {
return true
}
if dragged.width > dragWidth {
seekTime(time + 8.0)
seekTime(time + 5.0)
} else if dragged.width < -dragWidth {
seekTime(time - 10.0)
seekTime(time - 8.0)
}
} else {
if dragged.width > dragWidth {
@ -408,7 +455,7 @@ struct SVideoPlayer: View, EditItemDelegate {
item.cancelPendingSeeks()
}
player.seek(to: CMTime(seconds: time, preferredTimescale: CMTimeScale(600))){ _ in
player.seek(to: CMTime(seconds: time, preferredTimescale: CMTimeScale(600))) { _ in
// player.seek(to: CMTime(seconds: time, preferredTimescale: CMTimeScale(10000)),
// toleranceBefore: CMTime(seconds: 0.3, preferredTimescale: CMTimeScale(10000)),
// toleranceAfter: CMTime(seconds: 1.0, preferredTimescale: CMTimeScale(10000))){ _ in
@ -453,8 +500,7 @@ struct SVideoPlayer: View, EditItemDelegate {
player.replaceCurrentItem(with: model.currentPlayerItem())
playerLooper
seekTime(currentSnapshot.time)
}
else {
} else {
seekTime(currentSnapshot.time)
}
let height = player.currentItem!.presentationSize.height
@ -467,8 +513,7 @@ struct SVideoPlayer: View, EditItemDelegate {
model.dragOffset.width = currentSnapshot.offset.x
model.dragOffset.height = currentSnapshot.offset.y
// player.transformLayer()
}
else {
} else {
if model.zoomed && f > 0.0 {
if f < 0.6 {
f = f * CGFloat(LocalManager.sharedInstance.settings.scale)
@ -516,7 +561,7 @@ struct SVideoPlayer: View, EditItemDelegate {
if file.pathExtension != "mp4" {
file = file.appendingPathExtension("mp4")
}
print (file)
print(file)
var dur = c.length
if (dur < 0) {
return
@ -526,11 +571,10 @@ struct SVideoPlayer: View, EditItemDelegate {
progress: { p in
let percent = Int(p * 100)
savetext = "\(percent)"
})
{ url in
}) { url in
savetext = "saved"
}
var s : MediaModel;
var s: MediaModel;
if (c.type == ItemType.SNAPSHOT && c.parent != nil) {
s = c.parent!.toMediaModel()
do {
@ -543,12 +587,10 @@ struct SVideoPlayer: View, EditItemDelegate {
.appendingPathExtension("jpg")
try local.write(to: tfile)
}
}
catch {
} catch {
// ignore
}
}
else {
} else {
s = c.toMediaModel()
}
@ -571,7 +613,7 @@ struct SVideoPlayer: View, EditItemDelegate {
struct SVideoPlayer_Previews: PreviewProvider {
static var previews: some View {
SVideoPlayer(completionHandler: {b in}, model: SVideoModel(allItems: [MediaItem](),
SVideoPlayer(completionHandler: { b in }, model: SVideoModel(allItems: [MediaItem](),
currentSnapshot: MediaItem(name: "extern", path: "", root: "", type: ItemType.FAVROOT),
baseItem: MediaItem(name: "extern", path: "", root: "", type: ItemType.FAVROOT)
))

Loading…
Cancel
Save