diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index 8dd4c5545f..44bad97001 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -1554,7 +1554,7 @@ F79B645F26CA661600838ACA /* UIControl+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIControl+Extension.swift"; sourceTree = ""; }; F79B869A265E19D40085C0E0 /* NSMutableAttributedString+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSMutableAttributedString+Extension.swift"; sourceTree = ""; }; F79EDA9F26B004980007D134 /* NCPlayerToolBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCPlayerToolBar.swift; sourceTree = ""; }; - F79EDAA126B004980007D134 /* NCPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCPlayer.swift; sourceTree = ""; }; + F79EDAA126B004980007D134 /* NCPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = NCPlayer.swift; sourceTree = ""; }; F79FFB252A97C24A0055EEA4 /* NCNetworkingE2EEMarkFolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingE2EEMarkFolder.swift; sourceTree = ""; }; F7A03E2E2D425A14007AA677 /* NCFavoriteNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCFavoriteNavigationController.swift; sourceTree = ""; }; F7A03E322D426115007AA677 /* NCMoreNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMoreNavigationController.swift; sourceTree = ""; }; diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift index bead951ef1..15e991f3fb 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift @@ -7,7 +7,7 @@ import NextcloudKit import UIKit import MobileVLCKit -class NCPlayer: NSObject { +class NCPlayer: NSObject, VLCMediaDelegate { internal var url: URL? internal var player = VLCMediaPlayer() internal var dialogProvider: VLCDialogProvider? @@ -65,18 +65,21 @@ class NCPlayer: NSObject { self.url = url self.singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didSingleTapWith(gestureRecognizer:))) - print("Play URL: \(url)") - player.media = VLCMedia(url: url) + print("Playing URL: \(url)") + let media = VLCMedia(url: url) + + media.parse(options: url.isFileURL ? .fetchLocal : .fetchNetwork) + + player.media = media player.delegate = self dialogProvider = VLCDialogProvider(library: VLCLibrary.shared(), customUI: true) dialogProvider?.customRenderer = self - // player?.media?.addOption("--network-caching=500") player.media?.addOption(":http-user-agent=\(userAgent)") if let result = self.database.getVideo(metadata: metadata), - let resultPosition = result.position { + let resultPosition = result.position { position = resultPosition } @@ -209,15 +212,15 @@ extension NCPlayer: VLCMediaPlayerDelegate { switch player.state { case .stopped: - playerToolBar?.playButtonPlay() + playerToolBar?.showPlayButton() NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterPlayerStoppedPlaying) - print("Played mode: STOPPED") + print("Player mode: STOPPED") case .opening: - print("Played mode: OPENING") + print("Player mode: OPENING") case .buffering: - print("Played mode: BUFFERING") + print("Player mode: BUFFERING") case .ended: self.database.addVideo(metadata: self.metadata, position: 0) DispatchQueue.main.asyncAfter(deadline: .now() + 1) { @@ -225,10 +228,10 @@ extension NCPlayer: VLCMediaPlayerDelegate { self.restartAVPlayer(position: 0, pauseAfterPlay: !playRepeat) } } - playerToolBar?.playButtonPlay() - print("Played mode: ENDED") + playerToolBar?.showPlayButton() + print("Player mode: ENDED") case .error: - print("Played mode: ERROR") + print("Player mode: ERROR") case .playing: guard let playerToolBar = playerToolBar else { return } if playerToolBar.playerButtonView.isHidden { @@ -240,7 +243,7 @@ extension NCPlayer: VLCMediaPlayerDelegate { pauseAfterPlay = false self.viewerMediaPage?.updateCommandCenter(ncplayer: self, title: metadata.fileNameView) } else { - playerToolBar.playButtonPause() + playerToolBar.showPauseButton() // Set track audio/subtitle let data = self.database.getVideo(metadata: metadata) if let currentAudioTrackIndex = data?.currentAudioTrackIndex { @@ -256,24 +259,25 @@ extension NCPlayer: VLCMediaPlayerDelegate { } self.width = Int(size.width) self.height = Int(size.height) + playerToolBar.updatePlaybackPosition() playerToolBar.updateTopToolBar(videoSubTitlesIndexes: player.videoSubTitlesIndexes, audioTrackIndexes: player.audioTrackIndexes) self.database.addVideo(metadata: metadata, width: self.width, height: self.height, length: self.length) NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterPlayerIsPlaying) - print("Played mode: PLAYING") + print("Player mode: PLAYING") case .paused: NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterPlayerStoppedPlaying) - playerToolBar?.playButtonPlay() - print("Played mode: PAUSED") + playerToolBar?.showPlayButton() + print("Player mode: PAUSED") default: break } } func mediaPlayerTimeChanged(_ aNotification: Notification) { activityIndicator.stopAnimating() - playerToolBar?.update() + playerToolBar?.updatePlaybackPosition() } } diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift index 5b138cd7fe..ccb930df56 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift @@ -31,11 +31,13 @@ class NCPlayerToolBar: UIView { @IBOutlet weak var repeatButton: UIButton! enum sliderEventType { + case none case began case ended case moved } - var playbackSliderEvent: sliderEventType = .ended + + var playbackSliderEvent: sliderEventType = .none var isFullscreen: Bool = false var playRepeat: Bool = false @@ -143,20 +145,32 @@ class NCPlayerToolBar: UIView { MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = position } - public func update() { - guard let ncplayer = self.ncplayer, let length = ncplayer.player.media?.length.intValue else { return } + public func updatePlaybackPosition() { + guard let ncplayer = self.ncplayer, + let media = ncplayer.player.media else { + return + } + + let length = media.length.intValue + let position = ncplayer.player.position - let positionInSecond = position * Float(length / 1000) - // SLIDER & TIME + let currentSeconds = Double(position) * (Double(length) / 1000.0) + + let currentTimeObj = VLCTime(int: Int32(currentSeconds * 1000)) + let remainingTimeObj = VLCTime(int: Int32((Double(length) / 1000.0) - currentSeconds) * 1000) + + labelCurrentTime.text = currentTimeObj.stringValue == "--:--" ? "00:00" : currentTimeObj.stringValue + + let remaining = remainingTimeObj.stringValue + labelLeftTime.text = "-\(remaining)" + if playbackSliderEvent == .ended { playbackSlider.value = position } - labelCurrentTime.text = ncplayer.player.time.stringValue - labelLeftTime.text = ncplayer.player.remainingTime?.stringValue MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPMediaItemPropertyPlaybackDuration] = length / 1000 - MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyElapsedPlaybackTime] = positionInSecond + MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyElapsedPlaybackTime] = currentSeconds } public func updateTopToolBar(videoSubTitlesIndexes: [Any], audioTrackIndexes: [Any]) { @@ -184,13 +198,13 @@ class NCPlayerToolBar: UIView { }) } - func playButtonPause() { + func showPauseButton() { buttonImage = UIImage(systemName: "pause.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: pointSize))!.withTintColor(.white, renderingMode: .alwaysOriginal) playButton.setImage(buttonImage, for: .normal) MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 1 } - func playButtonPlay() { + func showPlayButton() { buttonImage = UIImage(systemName: "play.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: pointSize))!.withTintColor(.white, renderingMode: .alwaysOriginal) playButton.setImage(buttonImage, for: .normal) MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 0 @@ -407,7 +421,7 @@ extension NCPlayerToolBar { guard let metadata = self.metadata else { return } let storyboard = UIStoryboard(name: "NCSelect", bundle: nil) if let navigationController = storyboard.instantiateInitialViewController() as? UINavigationController, - let viewController = navigationController.topViewController as? NCSelect { + let viewController = navigationController.topViewController as? NCSelect { viewController.delegate = self viewController.typeOfCommandView = .nothing @@ -490,7 +504,7 @@ extension NCPlayerToolBar: NCSelectDelegate { // swiftlint:disable inclusive_language func addPlaybackSlave(type: String, metadata: tableMetadata) { - // swiftlint:enable inclusive_language + // swiftlint:enable inclusive_language let fileNameLocalPath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, fileName: metadata.fileNameView, userId: metadata.userId, urlBase: metadata.urlBase) if type == "subtitle" { diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift index 85d3021d85..48bc45de63 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift @@ -356,7 +356,7 @@ class NCViewerMediaPage: UIViewController { func clearCommandCenter() { UIApplication.shared.endReceivingRemoteControlEvents() - MPNowPlayingInfoCenter.default().nowPlayingInfo = [:] + MPNowPlayingInfoCenter.default().nowPlayingInfo = nil MPRemoteCommandCenter.shared().playCommand.isEnabled = false MPRemoteCommandCenter.shared().pauseCommand.isEnabled = false