marinofaggiana 3 years ago
parent
commit
54a356cdf6

+ 48 - 41
iOSClient/Viewer/NCViewerImage/NCViewerImage.storyboard

@@ -95,47 +95,6 @@
                                         <color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                         <nil key="highlightedColor"/>
                                     </label>
-                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sBp-t2-eFh" customClass="NCViewerVideoToolBar" customModule="Nextcloud" customModuleProvider="target">
-                                        <rect key="frame" x="25" y="636" width="364" height="100"/>
-                                        <subviews>
-                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8AB-hx-yqN">
-                                                <rect key="frame" x="324" y="10" width="30" height="30"/>
-                                                <constraints>
-                                                    <constraint firstAttribute="width" constant="30" id="6yU-23-dkA"/>
-                                                    <constraint firstAttribute="height" constant="30" id="hBk-Ku-BAd"/>
-                                                </constraints>
-                                                <color key="tintColor" systemColor="labelColor"/>
-                                                <state key="normal" image="audioOn"/>
-                                                <connections>
-                                                    <action selector="setMute:" destination="sBp-t2-eFh" eventType="touchUpInside" id="cVl-BA-mPJ"/>
-                                                </connections>
-                                            </button>
-                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="x3E-b2-obf">
-                                                <rect key="frame" x="167" y="60" width="30" height="30"/>
-                                                <constraints>
-                                                    <constraint firstAttribute="width" constant="30" id="Cmv-LX-Phg"/>
-                                                    <constraint firstAttribute="height" constant="30" id="djE-Ml-YD0"/>
-                                                </constraints>
-                                                <color key="tintColor" systemColor="labelColor"/>
-                                                <state key="normal" image="play.fill" catalog="system"/>
-                                                <connections>
-                                                    <action selector="playerPause:" destination="sBp-t2-eFh" eventType="touchUpInside" id="pRl-bT-hpi"/>
-                                                </connections>
-                                            </button>
-                                        </subviews>
-                                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                                        <constraints>
-                                            <constraint firstAttribute="trailing" secondItem="8AB-hx-yqN" secondAttribute="trailing" constant="10" id="4LY-8e-z3y"/>
-                                            <constraint firstAttribute="bottom" secondItem="x3E-b2-obf" secondAttribute="bottom" constant="10" id="7W8-qk-uwn"/>
-                                            <constraint firstAttribute="height" constant="100" id="EyI-HW-pHA"/>
-                                            <constraint firstItem="8AB-hx-yqN" firstAttribute="top" secondItem="sBp-t2-eFh" secondAttribute="top" constant="10" id="qca-CP-X1n"/>
-                                            <constraint firstItem="x3E-b2-obf" firstAttribute="centerX" secondItem="sBp-t2-eFh" secondAttribute="centerX" id="uPa-tM-Vx6"/>
-                                        </constraints>
-                                        <connections>
-                                            <outlet property="muteButton" destination="8AB-hx-yqN" id="9zQ-k7-auv"/>
-                                            <outlet property="playButton" destination="x3E-b2-obf" id="0Nw-L4-W7M"/>
-                                        </connections>
-                                    </view>
                                     <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="P8R-4f-zAl" customClass="NCViewerImageDetailView" customModule="Nextcloud" customModuleProvider="target">
                                         <rect key="frame" x="0.0" y="336" width="414" height="375"/>
                                         <subviews>
@@ -281,6 +240,54 @@
                                             <outlet property="sizeValue" destination="XLb-0a-du9" id="9jm-Ku-sgt"/>
                                         </connections>
                                     </view>
+                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sBp-t2-eFh" customClass="NCViewerVideoToolBar" customModule="Nextcloud" customModuleProvider="target">
+                                        <rect key="frame" x="25" y="636" width="364" height="100"/>
+                                        <subviews>
+                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8AB-hx-yqN">
+                                                <rect key="frame" x="324" y="60" width="30" height="30"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" constant="30" id="6yU-23-dkA"/>
+                                                    <constraint firstAttribute="height" constant="30" id="hBk-Ku-BAd"/>
+                                                </constraints>
+                                                <color key="tintColor" systemColor="labelColor"/>
+                                                <state key="normal" image="audioOn"/>
+                                                <connections>
+                                                    <action selector="setMute:" destination="sBp-t2-eFh" eventType="touchUpInside" id="cVl-BA-mPJ"/>
+                                                </connections>
+                                            </button>
+                                            <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="SR4-e8-1hC">
+                                                <rect key="frame" x="8" y="15" width="348" height="31"/>
+                                            </slider>
+                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="x3E-b2-obf">
+                                                <rect key="frame" x="167" y="60" width="30" height="30"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" constant="30" id="Cmv-LX-Phg"/>
+                                                    <constraint firstAttribute="height" constant="30" id="djE-Ml-YD0"/>
+                                                </constraints>
+                                                <color key="tintColor" systemColor="labelColor"/>
+                                                <state key="normal" image="play.fill" catalog="system"/>
+                                                <connections>
+                                                    <action selector="playerPause:" destination="sBp-t2-eFh" eventType="touchUpInside" id="pRl-bT-hpi"/>
+                                                </connections>
+                                            </button>
+                                        </subviews>
+                                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                        <constraints>
+                                            <constraint firstAttribute="trailing" secondItem="8AB-hx-yqN" secondAttribute="trailing" constant="10" id="4LY-8e-z3y"/>
+                                            <constraint firstAttribute="bottom" secondItem="x3E-b2-obf" secondAttribute="bottom" constant="10" id="7W8-qk-uwn"/>
+                                            <constraint firstAttribute="bottom" secondItem="8AB-hx-yqN" secondAttribute="bottom" constant="10" id="CUW-6d-CGn"/>
+                                            <constraint firstAttribute="height" constant="100" id="EyI-HW-pHA"/>
+                                            <constraint firstAttribute="trailing" secondItem="SR4-e8-1hC" secondAttribute="trailing" constant="10" id="Q3r-ex-Cpf"/>
+                                            <constraint firstItem="SR4-e8-1hC" firstAttribute="leading" secondItem="sBp-t2-eFh" secondAttribute="leading" constant="10" id="Xec-gd-9AB"/>
+                                            <constraint firstItem="x3E-b2-obf" firstAttribute="centerX" secondItem="sBp-t2-eFh" secondAttribute="centerX" id="uPa-tM-Vx6"/>
+                                            <constraint firstItem="SR4-e8-1hC" firstAttribute="top" secondItem="sBp-t2-eFh" secondAttribute="top" constant="15" id="uu1-ai-wmJ"/>
+                                        </constraints>
+                                        <connections>
+                                            <outlet property="muteButton" destination="8AB-hx-yqN" id="9zQ-k7-auv"/>
+                                            <outlet property="playButton" destination="x3E-b2-obf" id="0Nw-L4-W7M"/>
+                                            <outlet property="playbackSlider" destination="SR4-e8-1hC" id="Khx-Oe-NEQ"/>
+                                        </connections>
+                                    </view>
                                 </subviews>
                                 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                 <constraints>

+ 43 - 44
iOSClient/Viewer/NCViewerVideo/NCViewerVideo.swift

@@ -24,12 +24,11 @@
 import Foundation
 import NCCommunication
 
-class NCViewerVideo: NSObject {
+class NCViewerVideo: NSObject, AVAssetResourceLoaderDelegate {
     
     private let appDelegate = UIApplication.shared.delegate as! AppDelegate
     private var progressView: UIProgressView?
 
-    private var videoLayer: AVPlayerLayer?
     private var view: UIView?
     private var timeObserver: Any?
     private var rateObserver: Any?
@@ -37,6 +36,8 @@ class NCViewerVideo: NSObject {
     
     public var viewerVideoToolBar: NCViewerVideoToolBar?
     public var player: AVPlayer?
+    public var videoLayer: AVPlayerLayer?
+    public var playerItem: AVPlayerItem?
     public var pictureInPictureOcId: String = ""
     
     init(view: UIView?, progressView: UIProgressView?, viewerVideoToolBar: NCViewerVideoToolBar?) {
@@ -65,54 +66,56 @@ class NCViewerVideo: NSObject {
     
     func videoPlay(metadata: tableMetadata) {
         self.metadata = metadata
-        
-        NCKTVHTTPCache.shared.startProxy(user: appDelegate.user, password: appDelegate.password, metadata: metadata)
-        
-        func play(url: URL) {
-            
-            self.player = AVPlayer(url: url)
-            self.player?.isMuted = CCUtility.getAudioMute()
-            self.videoLayer = AVPlayerLayer(player: self.player)
-
-            if let view = view  {
-
-                self.videoLayer!.frame = view.bounds
-                self.videoLayer!.videoGravity = AVLayerVideoGravity.resizeAspectFill
-                view.layer.addSublayer(self.videoLayer!)
                 
-                // At end go back to start
-                NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem, queue: .main) { (notification) in
-                    if let item = notification.object as? AVPlayerItem, let currentItem = self.player?.currentItem, item == currentItem {
-                        self.player?.seek(to: .zero)
-                        if metadata.livePhoto {
-                            NCManageDatabase.shared.deleteVideoTime(metadata: metadata)
+       
+        if let view = view  {
+
+            NCNetworking.shared.getVideoUrl(metadata: metadata) { url in
+                if let url = url {
+                    let urlAsset = AVURLAsset(url: url)
+                    urlAsset.resourceLoader.setDelegate(self, queue: .main)
+                    
+                    self.playerItem = AVPlayerItem(asset: urlAsset)
+                    
+                    self.player = AVPlayer(playerItem: self.playerItem)
+                    self.player?.isMuted = CCUtility.getAudioMute()
+                    
+                    self.videoLayer = AVPlayerLayer(player: self.player)
+                    self.videoLayer?.frame = view.bounds
+                    self.videoLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
+                    view.layer.addSublayer(self.videoLayer!)
+                    
+                    // At end go back to start
+                    NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem, queue: .main) { (notification) in
+                        if let item = notification.object as? AVPlayerItem, let currentItem = self.player?.currentItem, item == currentItem {
+                            self.player?.seek(to: .zero)
+                            if metadata.livePhoto {
+                                NCManageDatabase.shared.deleteVideoTime(metadata: metadata)
+                            }
                         }
                     }
-                }
-                            
-                self.rateObserver = self.player?.addObserver(self, forKeyPath: "rate", options: [], context: nil)
-                
-                if self.pictureInPictureOcId != metadata.ocId {
-                    self.player?.play()
+                    
+                    self.rateObserver = self.player?.addObserver(self, forKeyPath: "rate", options: [], context: nil)
+                    
+                    if self.pictureInPictureOcId != metadata.ocId {
+                        self.player?.play()
+                    }
+                    
+                    // TOOLBAR
+                    self.viewerVideoToolBar?.setPlayer(player: self.player)
+                    self.viewerVideoToolBar?.setToolBar()
                 }
             }
-            
-            // TOOLBAR
-            viewerVideoToolBar?.setPlayer(player: player)
-            viewerVideoToolBar?.setToolBar()
-        }
-        
-        //NCNetworking.shared.getVideoUrl(metadata: metadata) { url in
-        //            if let url = url {
-
-        if let url = NCKTVHTTPCache.shared.getVideoURL(metadata: metadata) {
-            play(url: url)
         }
     }
     
+    func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForResponseTo authenticationChallenge: URLAuthenticationChallenge) -> Bool {
+        return true
+    }
+    
     func videoStop() {
         
-        guard let metadata = self.metadata else { return }
+       // guard let metadata = self.metadata else { return }
         
         player?.pause()
         player?.seek(to: CMTime.zero)
@@ -126,7 +129,6 @@ class NCViewerVideo: NSObject {
         if rateObserver != nil {
             player?.removeObserver(self, forKeyPath: "rate")
             NotificationCenter.default.removeObserver(self, name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
-            NCKTVHTTPCache.shared.stopProxy(metadata: metadata)
             self.rateObserver = nil
         }
                
@@ -183,8 +185,5 @@ class NCViewerVideo: NSObject {
             }
         }
     }
-    
-
-    
 }
 

+ 29 - 1
iOSClient/Viewer/NCViewerVideo/NCViewerVideoToolBar.swift

@@ -27,7 +27,8 @@ class NCViewerVideoToolBar: UIView {
     
     @IBOutlet weak var playButton: UIButton!
     @IBOutlet weak var muteButton: UIButton!
-    
+    @IBOutlet weak var playbackSlider: UISlider!
+
     var player: AVPlayer?
     
     override func willMove(toWindow newWindow: UIWindow?) {
@@ -49,6 +50,22 @@ class NCViewerVideoToolBar: UIView {
     
     func setPlayer(player: AVPlayer?) {
         self.player = player
+        
+        let duration: CMTime = (player?.currentItem?.asset.duration)!
+        let seconds: Float64 = CMTimeGetSeconds(duration)
+        
+        playbackSlider.minimumValue = 0
+        playbackSlider.maximumValue = Float(seconds)
+        playbackSlider.isContinuous = true
+        playbackSlider.tintColor = UIColor.green
+        playbackSlider.action(for: .valueChanged) { _ in
+            let seconds : Int64 = Int64(self.playbackSlider.value)
+            let targetTime:CMTime = CMTimeMake(value: seconds, timescale: 1)
+            self.player?.seek(to: targetTime)
+            if self.player?.rate == 0 {
+                self.player?.play()
+            }
+        }
     }
     
     func setToolBar() {
@@ -86,4 +103,15 @@ class NCViewerVideoToolBar: UIView {
         setToolBar()
     }
     
+    @objc func playbackSliderValueChanged(_ playbackSlider:UISlider) {
+           
+           let seconds : Int64 = Int64(playbackSlider.value)
+           let targetTime:CMTime = CMTimeMake(value: seconds, timescale: 1)
+           
+           player?.seek(to: targetTime)
+           
+           if player?.rate == 0 {
+               player?.play()
+           }
+       }
 }